source: TFP-WebServer/SpaceWizards.HttpListener/src/System/Net/Managed/HttpListenerContext.Managed.cs

Last change on this file was 377, checked in by alloc, 2 years ago

Made SpaceWizards.HttpListener compilable against .NET 4.8 with preprocessor define UNITY_NETFRAMEWORK

File size: 4.6 KB
Line 
1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3
4// ReSharper disable RedundantUsingDirective
5// ReSharper disable RedundantUnsafeContext
6// ReSharper disable UnusedVariable
7#pragma warning disable CS8604
8
9using System;
10using System.ComponentModel;
11using System.Diagnostics.CodeAnalysis;
12using System.Net;
13using System.Net.WebSockets;
14using System.Security.Principal;
15using System.Text;
16using System.Threading.Tasks;
17using SpaceWizards.HttpListener.WebSockets;
18using HttpListenerWebSocketContext = SpaceWizards.HttpListener.WebSockets.HttpListenerWebSocketContext;
19using HttpWebSocket = SpaceWizards.HttpListener.WebSockets.HttpWebSocket;
20
21namespace SpaceWizards.HttpListener
22{
23 public sealed unsafe partial class HttpListenerContext
24 {
25 private HttpConnection _connection;
26
27 internal HttpListenerContext(HttpConnection connection)
28 {
29 _connection = connection;
30 _response = new HttpListenerResponse(this);
31 Request = new HttpListenerRequest(this);
32 ErrorStatus = 400;
33 }
34
35 internal int ErrorStatus { get; set; }
36
37 internal string? ErrorMessage { get; set; }
38
39 internal bool HaveError => ErrorMessage != null;
40
41 internal HttpConnection Connection => _connection;
42
43 internal void ParseAuthentication(AuthenticationSchemes expectedSchemes)
44 {
45 if (expectedSchemes == AuthenticationSchemes.Anonymous)
46 return;
47
48 string? header = Request.Headers[HttpKnownHeaderNames.Authorization];
49 if (string.IsNullOrEmpty(header))
50 return;
51
52 if (IsBasicHeader(header))
53 {
54 _user = ParseBasicAuthentication(header.Substring(AuthenticationTypes.Basic.Length + 1));
55 }
56 }
57
58 internal IPrincipal? ParseBasicAuthentication(string authData) =>
59 TryParseBasicAuth(authData, out HttpStatusCode errorCode, out string? username, out string? password) ?
60 new GenericPrincipal(new HttpListenerBasicIdentity(username, password), Array.Empty<string>()) :
61 null;
62
63 internal static bool IsBasicHeader(string header) =>
64 header.Length >= 6 &&
65 header[5] == ' ' &&
66 string.Compare(header, 0, AuthenticationTypes.Basic, 0, 5, StringComparison.OrdinalIgnoreCase) == 0;
67
68#if UNITY_NETFRAMEWORK
69 internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, out string? username, out string? password)
70#else
71 internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, [NotNullWhen(true)] out string? username, [NotNullWhen(true)] out string? password)
72#endif
73 {
74 errorCode = HttpStatusCode.OK;
75 username = password = null;
76 try
77 {
78 if (string.IsNullOrWhiteSpace(headerValue))
79 {
80 return false;
81 }
82
83 string authString = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue));
84 int colonPos = authString.IndexOf(':');
85 if (colonPos < 0)
86 {
87 // username must be at least 1 char
88 errorCode = HttpStatusCode.BadRequest;
89 return false;
90 }
91
92 username = authString.Substring(0, colonPos);
93 password = authString.Substring(colonPos + 1);
94 return true;
95 }
96 catch
97 {
98 errorCode = HttpStatusCode.InternalServerError;
99 return false;
100 }
101 }
102
103#if !UNITY_NETFRAMEWORK
104 public Task<WebSockets.HttpListenerWebSocketContext> AcceptWebSocketAsync(string? subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval)
105 {
106 return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval);
107 }
108
109 [EditorBrowsable(EditorBrowsableState.Never)]
110 public Task<WebSockets.HttpListenerWebSocketContext> AcceptWebSocketAsync(string? subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment<byte> internalBuffer)
111 {
112 WebSocketValidate.ValidateArraySegment(internalBuffer, nameof(internalBuffer));
113 HttpWebSocket.ValidateOptions(subProtocol, receiveBufferSize, HttpWebSocket.MinSendBufferSize, keepAliveInterval);
114 return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
115 }
116#endif
117 }
118}
Note: See TracBrowser for help on using the repository browser.