diff options
Diffstat (limited to 'lib/Net.Http')
-rw-r--r-- | lib/Net.Http/src/Core/ConnectionInfo.cs | 32 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/HttpContext.cs | 11 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/HttpServerProcessing.cs | 23 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/IConnectionContext.cs | 2 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/IHttpContextInformation.cs | 5 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/Request/HttpRequest.cs | 7 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/Request/HttpRequestExtensions.cs | 2 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs | 6 | ||||
-rw-r--r-- | lib/Net.Http/src/Helpers/HelperTypes.cs | 29 | ||||
-rw-r--r-- | lib/Net.Http/src/IConnectionInfo.cs | 21 | ||||
-rw-r--r-- | lib/Net.Http/src/IHttpServer.cs | 5 | ||||
-rw-r--r-- | lib/Net.Http/src/ITransportContext.cs | 12 | ||||
-rw-r--r-- | lib/Net.Http/src/IWebRoot.cs | 10 | ||||
-rw-r--r-- | lib/Net.Http/src/TransportSecurityInfo.cs | 10 |
14 files changed, 89 insertions, 86 deletions
diff --git a/lib/Net.Http/src/Core/ConnectionInfo.cs b/lib/Net.Http/src/Core/ConnectionInfo.cs index 8a1525c..fb22fe3 100644 --- a/lib/Net.Http/src/Core/ConnectionInfo.cs +++ b/lib/Net.Http/src/Core/ConnectionInfo.cs @@ -39,44 +39,70 @@ namespace VNLib.Net.Http ///<inheritdoc/> public Uri RequestUri => Context.Request.Location; + ///<inheritdoc/> public string Path => RequestUri.LocalPath; + ///<inheritdoc/> public string? UserAgent => Context.Request.UserAgent; + ///<inheritdoc/> public IHeaderCollection Headers { get; private set; } + ///<inheritdoc/> public bool CrossOrigin { get; } + ///<inheritdoc/> public bool IsWebSocketRequest { get; } + ///<inheritdoc/> public ContentType ContentType => Context.Request.ContentType; + ///<inheritdoc/> public HttpMethod Method => Context.Request.Method; + ///<inheritdoc/> public HttpVersion ProtocolVersion => Context.Request.HttpVersion; + ///<inheritdoc/> - public bool IsSecure => Context.Request.EncryptionVersion != SslProtocols.None; + public bool IsSecure => SecurityProtocol != SslProtocols.None; + ///<inheritdoc/> - public SslProtocols SecurityProtocol => Context.Request.EncryptionVersion; + public SslProtocols SecurityProtocol + { + get + { + ref readonly TransportSecurityInfo? securityInfo = ref Context.GetSecurityInfo(); + return securityInfo.HasValue ? securityInfo.Value.SslProtocol : SslProtocols.None; + } + } + ///<inheritdoc/> public Uri? Origin => Context.Request.Origin; + ///<inheritdoc/> public Uri? Referer => Context.Request.Referrer; + ///<inheritdoc/> public Tuple<long, long>? Range => Context.Request.Range; + ///<inheritdoc/> public IPEndPoint LocalEndpoint => Context.Request.LocalEndPoint; + ///<inheritdoc/> public IPEndPoint RemoteEndpoint => Context.Request.RemoteEndPoint; + ///<inheritdoc/> public Encoding Encoding => Context.ParentServer.Config.HttpEncoding; + ///<inheritdoc/> public IReadOnlyDictionary<string, string> RequestCookies => Context.Request.Cookies; + ///<inheritdoc/> public IReadOnlyCollection<string> Accept => Context.Request.Accept; + ///<inheritdoc/> - public TransportSecurityInfo? TransportSecurity => Context.GetSecurityInfo(); + public ref readonly TransportSecurityInfo? GetTransportSecurityInfo() => ref Context.GetSecurityInfo(); ///<inheritdoc/> public void SetCookie(string name, string value, string? domain, string? path, TimeSpan Expires, CookieSameSite sameSite, bool httpOnly, bool secure) diff --git a/lib/Net.Http/src/Core/HttpContext.cs b/lib/Net.Http/src/Core/HttpContext.cs index 3e25e70..f0cd3f8 100644 --- a/lib/Net.Http/src/Core/HttpContext.cs +++ b/lib/Net.Http/src/Core/HttpContext.cs @@ -114,7 +114,11 @@ namespace VNLib.Net.Http.Core ContextFlags = new(0); } - public TransportSecurityInfo? GetSecurityInfo() => _ctx?.GetSecurityInfo(); + /// <summary> + /// Gets a readonly reference to the transport security information + /// </summary> + /// <returns>A readonly referrence to the <see cref="TransportSecurityInfo"/> structure </returns> + public ref readonly TransportSecurityInfo? GetSecurityInfo() => ref _ctx!.GetSecurityInfo(); #region Context information @@ -125,9 +129,6 @@ namespace VNLib.Net.Http.Core HttpVersion IHttpContextInformation.CurrentVersion => Request.HttpVersion; ///<inheritdoc/> - HttpConfig IHttpContextInformation.Config => ParentServer.Config; - - ///<inheritdoc/> public ServerPreEncodedSegments EncodedSegments => ParentServer.PreEncodedSegments; ///<inheritdoc/> @@ -164,7 +165,7 @@ namespace VNLib.Net.Http.Core } ///<inheritdoc/> - public Task FlushTransportAsnc() + public Task FlushTransportAsync() { return _ctx!.ConnectionStream.FlushAsync(); } diff --git a/lib/Net.Http/src/Core/HttpServerProcessing.cs b/lib/Net.Http/src/Core/HttpServerProcessing.cs index d3c5981..6c5fd43 100644 --- a/lib/Net.Http/src/Core/HttpServerProcessing.cs +++ b/lib/Net.Http/src/Core/HttpServerProcessing.cs @@ -201,8 +201,8 @@ namespace VNLib.Net.Http //Close the response await context.WriteResponseAsync(); - //Flush the stream before retuning - await context.FlushTransportAsnc(); + //Flush the stream before returning + await context.FlushTransportAsync(); /* * If an alternate protocol was specified, we need to break the keepalive loop @@ -236,6 +236,14 @@ namespace VNLib.Net.Http [MethodImpl(MethodImplOptions.AggressiveOptimization)] private HttpStatusCode ParseRequest(HttpContext ctx) { + //Get transport security info + ref readonly TransportSecurityInfo? secInfo = ref ctx.GetSecurityInfo(); + + if (secInfo.HasValue) + { + //TODO: future support for http2 and http3 over tls + } + //Get the parse buffer IHttpHeaderParseBuffer parseBuffer = ctx.Buffers.RequestHeaderParseBuffer; @@ -250,7 +258,7 @@ namespace VNLib.Net.Http Http11ParseExtensions.Http1ParseState parseState = new(); //Parse the request line - HttpStatusCode code = ctx.Request.Http1ParseRequestLine(ref parseState, ref reader, lineBuf); + HttpStatusCode code = ctx.Request.Http1ParseRequestLine(ref parseState, ref reader, lineBuf, secInfo.HasValue); if (code > 0) { @@ -355,15 +363,6 @@ namespace VNLib.Net.Http return keepalive; } - //check for redirects - if (root.Redirects.TryGetValue(context.Request.Location.LocalPath, out Redirect? r)) - { - //301 - context.Redirect301(r.RedirectUrl); - //Return keepalive - return keepalive; - } - //Check the expect header and return an early status code if (context.Request.Expect) { diff --git a/lib/Net.Http/src/Core/IConnectionContext.cs b/lib/Net.Http/src/Core/IConnectionContext.cs index fd12d74..9654964 100644 --- a/lib/Net.Http/src/Core/IConnectionContext.cs +++ b/lib/Net.Http/src/Core/IConnectionContext.cs @@ -55,7 +55,7 @@ namespace VNLib.Net.Http.Core /// Flushes and pending data associated with the request to the transport /// </summary> /// <returns>A task that represents the flush operation</returns> - Task FlushTransportAsnc(); + Task FlushTransportAsync(); /// <summary> /// Signals to the context that it will release any request specific diff --git a/lib/Net.Http/src/Core/IHttpContextInformation.cs b/lib/Net.Http/src/Core/IHttpContextInformation.cs index ba1566b..fbe079f 100644 --- a/lib/Net.Http/src/Core/IHttpContextInformation.cs +++ b/lib/Net.Http/src/Core/IHttpContextInformation.cs @@ -46,11 +46,6 @@ namespace VNLib.Net.Http.Core HttpVersion CurrentVersion { get; } /// <summary> - /// The current server configuration - /// </summary> - HttpConfig Config { get; } - - /// <summary> /// Gets the transport stream for the current connection. /// </summary> /// <returns>The current transport stream</returns> diff --git a/lib/Net.Http/src/Core/Request/HttpRequest.cs b/lib/Net.Http/src/Core/Request/HttpRequest.cs index 06168bc..cf21b19 100644 --- a/lib/Net.Http/src/Core/Request/HttpRequest.cs +++ b/lib/Net.Http/src/Core/Request/HttpRequest.cs @@ -25,7 +25,6 @@ using System; using System.Net; using System.Collections.Generic; -using System.Security.Authentication; using System.Runtime.CompilerServices; using VNLib.Utils; @@ -57,19 +56,20 @@ namespace VNLib.Net.Http.Core public Uri? Referrer { get; set; } internal bool KeepAlive { get; set; } public IPEndPoint RemoteEndPoint { get; set; } - public IPEndPoint LocalEndPoint { get; set; } - public SslProtocols EncryptionVersion { get; set; } + public IPEndPoint LocalEndPoint { get; set; } public Tuple<long, long>? Range { get; set; } /// <summary> /// A value indicating whether the connection contained a request entity body. /// </summary> public bool HasEntityBody { get; set; } + /// <summary> /// A transport stream wrapper that is positioned for reading /// the entity body from the input stream /// </summary> public HttpInputStream InputStream { get; } + /// <summary> /// A value indicating if the client's request had an Expect-100-Continue header /// </summary> @@ -104,7 +104,6 @@ namespace VNLib.Net.Http.Core { //Set to defaults ContentType = ContentType.NonSupported; - EncryptionVersion = default; Method = HttpMethod.None; HttpVersion = HttpVersion.None; } diff --git a/lib/Net.Http/src/Core/Request/HttpRequestExtensions.cs b/lib/Net.Http/src/Core/Request/HttpRequestExtensions.cs index f92a685..0da2e98 100644 --- a/lib/Net.Http/src/Core/Request/HttpRequestExtensions.cs +++ b/lib/Net.Http/src/Core/Request/HttpRequestExtensions.cs @@ -27,6 +27,7 @@ using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; +using System.Security.Authentication; using System.Runtime.CompilerServices; using VNLib.Utils.IO; @@ -126,7 +127,6 @@ namespace VNLib.Net.Http.Core { server.LocalEndPoint = ctx.LocalEndPoint; server.RemoteEndPoint = ctx.RemoteEndpoint; - server.EncryptionVersion = ctx.SslVersion; //Set to default http version so the response can be configured properly server.HttpVersion = defaultHttpVersion; } diff --git a/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs b/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs index c25cd12..de65e12 100644 --- a/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs +++ b/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs @@ -27,7 +27,6 @@ using System.Net; using System.Linq; using System.Buffers; using System.Collections.Generic; -using System.Security.Authentication; using System.Runtime.CompilerServices; using VNLib.Utils; @@ -64,10 +63,11 @@ namespace VNLib.Net.Http.Core /// <param name="reader">The reader to read lines from the transport</param> /// <param name="parseState">The HTTP1 parsing state</param> /// <param name="lineBuf">The buffer to use when parsing the request data</param> + /// <param name="usingTls">True if the transport is using TLS</param> /// <returns>0 if the request line was successfully parsed, a status code if the request could not be processed</returns> /// <exception cref="UriFormatException"></exception> [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] - public static HttpStatusCode Http1ParseRequestLine(this HttpRequest Request, ref Http1ParseState parseState, ref TransportReader reader, Span<char> lineBuf) + public static HttpStatusCode Http1ParseRequestLine(this HttpRequest Request, ref Http1ParseState parseState, ref TransportReader reader, Span<char> lineBuf, bool usingTls) { //Locals ERRNO requestResult; @@ -141,7 +141,7 @@ namespace VNLib.Net.Http.Core parseState.Location = new() { //Set a default scheme - Scheme = Request.EncryptionVersion == SslProtocols.None ? Uri.UriSchemeHttp : Uri.UriSchemeHttps, + Scheme = usingTls ? Uri.UriSchemeHttp : Uri.UriSchemeHttps, }; //Need to manually parse the query string diff --git a/lib/Net.Http/src/Helpers/HelperTypes.cs b/lib/Net.Http/src/Helpers/HelperTypes.cs index ecdb28c..8b03dbf 100644 --- a/lib/Net.Http/src/Helpers/HelperTypes.cs +++ b/lib/Net.Http/src/Helpers/HelperTypes.cs @@ -172,33 +172,4 @@ namespace VNLib.Net.Http /// </summary> SameSite } - - /// <summary> - /// Low level 301 "hard" redirect - /// </summary> - public class Redirect - { - public readonly string Url; - public readonly Uri RedirectUrl; - /// <summary> - /// Quickly redirects a url to another url before sessions are established - /// </summary> - /// <param name="url">Url to redirect on</param> - /// <param name="redirecturl">Url to redirect to</param> - public Redirect(string url, string redirecturl) - { - if (string.IsNullOrEmpty(url)) - { - throw new ArgumentException($"'{nameof(url)}' cannot be null or empty.", nameof(url)); - } - - if (string.IsNullOrEmpty(redirecturl)) - { - throw new ArgumentException($"'{nameof(redirecturl)}' cannot be null or empty.", nameof(redirecturl)); - } - - Url = url; - RedirectUrl = new(redirecturl); - } - } }
\ No newline at end of file diff --git a/lib/Net.Http/src/IConnectionInfo.cs b/lib/Net.Http/src/IConnectionInfo.cs index 0feedd9..5664ac5 100644 --- a/lib/Net.Http/src/IConnectionInfo.cs +++ b/lib/Net.Http/src/IConnectionInfo.cs @@ -40,84 +40,103 @@ namespace VNLib.Net.Http /// Full request uri of current connection /// </summary> Uri RequestUri { get; } + /// <summary> /// Current request path. Shortcut to <seealso cref="RequestUri"/> <see cref="Uri.LocalPath"/> /// </summary> string Path => RequestUri.LocalPath; + /// <summary> /// Current connection's user-agent header, (may be null if no user-agent header found) /// </summary> string? UserAgent { get; } + /// <summary> /// Current connection's headers /// </summary> IHeaderCollection Headers { get; } + /// <summary> /// A value that indicates if the connection's origin header was set and it's /// authority segment does not match the <see cref="RequestUri"/> authority /// segment. /// </summary> bool CrossOrigin { get; } + /// <summary> /// Is the current connecion a websocket request /// </summary> bool IsWebSocketRequest { get; } + /// <summary> /// Request specified content-type /// </summary> ContentType ContentType { get; } + /// <summary> /// Current request's method /// </summary> HttpMethod Method { get; } + /// <summary> /// The current connection's HTTP protocol version /// </summary> HttpVersion ProtocolVersion { get; } + /// <summary> /// Is the connection using transport security? /// </summary> bool IsSecure { get; } + /// <summary> /// The negotiated transport protocol for the current connection /// </summary> SslProtocols SecurityProtocol { get; } + /// <summary> /// Origin header of current connection if specified, null otherwise /// </summary> Uri? Origin { get; } + /// <summary> /// Referer header of current connection if specified, null otherwise /// </summary> Uri? Referer { get; } + /// <summary> /// The parsed range header, or -1,-1 if the range header was not set /// </summary> Tuple<long, long>? Range { get; } + /// <summary> /// The server endpoint that accepted the connection /// </summary> IPEndPoint LocalEndpoint { get; } + /// <summary> /// The raw <see cref="IPEndPoint"/> of the downstream connection. /// </summary> IPEndPoint RemoteEndpoint { get; } + /// <summary> /// The encoding type used to decode and encode character data to and from the current client /// </summary> Encoding Encoding { get; } + /// <summary> /// A <see cref="IReadOnlyDictionary{TKey, TValue}"/> of client request cookies /// </summary> IReadOnlyDictionary<string, string> RequestCookies { get; } + /// <summary> /// Gets an <see cref="IEnumerator{T}"/> for the parsed accept header values /// </summary> IReadOnlyCollection<string> Accept { get; } + /// <summary> /// Gets the underlying transport security information for the current connection /// </summary> - TransportSecurityInfo? TransportSecurity { get; } + ref readonly TransportSecurityInfo? GetTransportSecurityInfo(); /// <summary> diff --git a/lib/Net.Http/src/IHttpServer.cs b/lib/Net.Http/src/IHttpServer.cs index ccee8fd..dea477a 100644 --- a/lib/Net.Http/src/IHttpServer.cs +++ b/lib/Net.Http/src/IHttpServer.cs @@ -33,11 +33,6 @@ namespace VNLib.Net.Http public interface IHttpServer { /// <summary> - /// The <see cref="HttpConfig"/> for the current server - /// </summary> - HttpConfig Config { get; } - - /// <summary> /// Gets a value indicating whether the server is listening for connections /// </summary> bool Running { get; } diff --git a/lib/Net.Http/src/ITransportContext.cs b/lib/Net.Http/src/ITransportContext.cs index bd6ce05..622dec4 100644 --- a/lib/Net.Http/src/ITransportContext.cs +++ b/lib/Net.Http/src/ITransportContext.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -25,8 +25,6 @@ using System.IO; using System.Net; using System.Threading.Tasks; -using System.Security.Authentication; - namespace VNLib.Net.Http { @@ -39,14 +37,12 @@ namespace VNLib.Net.Http /// The transport network stream for application data marshaling /// </summary> Stream ConnectionStream { get; } - /// <summary> - /// The transport security layer security protocol - /// </summary> - SslProtocols SslVersion { get; } + /// <summary> /// A copy of the local endpoint of the listening socket /// </summary> IPEndPoint LocalEndPoint { get; } + /// <summary> /// The <see cref="IPEndPoint"/> representing the client's connection information /// </summary> @@ -66,6 +62,6 @@ namespace VNLib.Net.Http /// Attemts to get the transport security details for the connection /// </summary> /// <returns>A the <see cref="TransportSecurityInfo"/> structure if applicable, null otherwise</returns> - TransportSecurityInfo? GetSecurityInfo(); + ref readonly TransportSecurityInfo? GetSecurityInfo(); } }
\ No newline at end of file diff --git a/lib/Net.Http/src/IWebRoot.cs b/lib/Net.Http/src/IWebRoot.cs index 9b1a9c8..d5a7e60 100644 --- a/lib/Net.Http/src/IWebRoot.cs +++ b/lib/Net.Http/src/IWebRoot.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -24,8 +24,6 @@ using System; using System.Threading.Tasks; -using System.Collections.Generic; - namespace VNLib.Net.Http { @@ -35,10 +33,12 @@ namespace VNLib.Net.Http /// </summary> public interface IWebRoot { + /// <summary> /// The hostname the server will listen for, and the hostname that will identify this root when a connection requests it /// </summary> string Hostname { get; } + /// <summary> /// <para> /// The main event handler for user code to process a request @@ -50,9 +50,5 @@ namespace VNLib.Net.Http /// <param name="httpEvent">An active, unprocessed event capturing the request infomration into a standard format</param> /// <returns>A <see cref="ValueTask"/> that the processor will await until the entity has been processed</returns> ValueTask ClientConnectedAsync(IHttpEvent httpEvent); - /// <summary> - /// "Low-Level" 301 redirects - /// </summary> - IReadOnlyDictionary<string, Redirect> Redirects { get; } } }
\ No newline at end of file diff --git a/lib/Net.Http/src/TransportSecurityInfo.cs b/lib/Net.Http/src/TransportSecurityInfo.cs index 7c7a79c..2d84a4c 100644 --- a/lib/Net.Http/src/TransportSecurityInfo.cs +++ b/lib/Net.Http/src/TransportSecurityInfo.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -35,8 +35,14 @@ namespace VNLib.Net.Http /// <summary> /// Gets the transport TLS security information for the current connection /// </summary> - public readonly struct TransportSecurityInfo + public readonly record struct TransportSecurityInfo { + + /// <summary> + /// The transport security layer security protocol + /// </summary> + public readonly SslProtocols SslProtocol { get; init; } + /// <summary> /// Gets a Boolean value that indicates whether the certificate revocation list is checked during the certificate validation process. /// </summary> |