From 01a654ff9a890be316734a42a207bf2dc14439c0 Mon Sep 17 00:00:00 2001 From: vnugent Date: Wed, 6 Dec 2023 14:20:15 -0500 Subject: package updates and prep for http updates --- .../VNLib.Net.CompressionTests.csproj | 2 +- lib/Net.Http/src/Core/Request/HttpInputStream.cs | 56 ++++++++++++++++--- lib/Net.Http/src/Helpers/HttpHelpers.cs | 64 ++++++++++------------ lib/Net.Http/src/Helpers/MimeLookups.cs | 13 +++-- 4 files changed, 86 insertions(+), 49 deletions(-) diff --git a/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj b/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj index 56c67ed..53a6155 100644 --- a/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj +++ b/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj @@ -8,7 +8,7 @@ - + diff --git a/lib/Net.Http/src/Core/Request/HttpInputStream.cs b/lib/Net.Http/src/Core/Request/HttpInputStream.cs index 3f6b2a5..7c010a3 100644 --- a/lib/Net.Http/src/Core/Request/HttpInputStream.cs +++ b/lib/Net.Http/src/Core/Request/HttpInputStream.cs @@ -26,6 +26,7 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; +using System.Diagnostics; using System.Runtime.CompilerServices; using VNLib.Utils; @@ -50,6 +51,7 @@ namespace VNLib.Net.Http.Core public HttpInputStream(IHttpContextInformation contextInfo) => ContextInfo = contextInfo; + private long Remaining => Math.Max(ContentLength - _position, 0); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void OnComplete() @@ -82,18 +84,53 @@ namespace VNLib.Net.Http.Core return ref _initalData; } - public override void Close() => throw new NotSupportedException("The HTTP input stream should never be closed!"); - private long Remaining => Math.Max(ContentLength - _position, 0); + /// + /// Not a supported method. In debug mode will cause the application to crash with a + /// warning to determine the cause. + /// + public override void Close() => Debug.Fail("A attempt to close the HTTP input stream was made. The source should be determined."); + + /// + /// Always returns true + /// public override bool CanRead => true; + + /// + /// Stream is not seekable, but is always true for + /// stream compatibility reasons + /// public override bool CanSeek => true; + + /// + /// Stream is never writable + /// public override bool CanWrite => false; + + /// + /// Gets the total size of the entity body (aka Content-Length) + /// public override long Length => ContentLength; + + /// + /// Gets the number of bytes currently read from the entity body, setting the + /// position is a NOOP + /// public override long Position { get => _position; set { } } + /// + /// NOOP + /// public override void Flush() { } + /// public override int Read(byte[] buffer, int offset, int count) => Read(buffer.AsSpan(offset, count)); + /// + /// Reads as much entity body data as available into the specified buffer as possible + /// until the buffer is full or the amount of entity data is reached. + /// + /// The buffer to copy entity data to + /// The number of bytes read from the transport public override int Read(Span buffer) { //Calculate the amount of data that can be read into the buffer @@ -135,6 +172,7 @@ namespace VNLib.Net.Http.Core return writer.Written; } + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { return ReadAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask(); @@ -221,14 +259,18 @@ namespace VNLib.Net.Http.Core } while (read != 0); } - public override long Seek(long offset, SeekOrigin origin) - { - //Ignore seek control - return _position; - } + /// + /// Seek is not a supported operation, a seek request is ignored and nothin happens + /// + /// + /// + /// + public override long Seek(long offset, SeekOrigin origin) => _position; + /// public override void SetLength(long value) => throw new NotSupportedException(); + /// public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); } } \ No newline at end of file diff --git a/lib/Net.Http/src/Helpers/HttpHelpers.cs b/lib/Net.Http/src/Helpers/HttpHelpers.cs index 198396f..a4486cd 100644 --- a/lib/Net.Http/src/Helpers/HttpHelpers.cs +++ b/lib/Net.Http/src/Helpers/HttpHelpers.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -25,6 +25,7 @@ using System; using System.IO; using System.Net; +using System.Linq; using System.Net.Sockets; using System.Collections.Generic; using System.Text.RegularExpressions; @@ -127,7 +128,7 @@ namespace VNLib.Net.Http * during request parsing) * */ - private static readonly IReadOnlyDictionary RequestHeaderHashLookup = HashRequestHeaders(); + private static readonly IReadOnlyDictionary RequestHeaderHashLookup = ComputeCodeHashLookup(RequestHeaderLookup); /* * Provides a constant lookup table for http version hashcodes to an http @@ -164,42 +165,22 @@ namespace VNLib.Net.Http private static IReadOnlyDictionary HashHttpMethods() { /* - * Http methods are hashed at runtime using the HttpMethod enum - * values, purley for compatability and automation - */ - Dictionary methods = new(); - //Add all HTTP methods - foreach (HttpMethod method in Enum.GetValues()) - { + * Http methods are hashed at runtime using the HttpMethod enum + * values, purley for compatability and automation + */ + return ComputeCodeHashLookup( + Enum.GetValues() //Exclude the not supported method - if (method == HttpMethod.None) - { - continue; - } - //Store method string's hashcode for faster lookups - methods[string.GetHashCode(method.ToString(), StringComparison.OrdinalIgnoreCase)] = method; - } - return methods; + .Except(new HttpMethod[] { HttpMethod.None }) + .Select(m => KeyValuePair.Create(m.ToString(), m)) + ); } - private static IReadOnlyDictionary HashRequestHeaders() - { - /* - * Pre-compute common headers - */ - Dictionary requestHeaderHashes = new(); - - //Add all HTTP methods - foreach (string headerValue in RequestHeaderLookup.Keys) - { - //Compute the hashcode for the header value - int hashCode = string.GetHashCode(headerValue, StringComparison.OrdinalIgnoreCase); - //Store the http header enum value with the hash-code of the string of said header - requestHeaderHashes[hashCode] = RequestHeaderLookup[headerValue]; - } - return requestHeaderHashes; - } - + private static IReadOnlyDictionary ComputeCodeHashLookup(IEnumerable> enumerable) + => enumerable.ToDictionary( + static kv => string.GetHashCode(kv.Key, StringComparison.OrdinalIgnoreCase), + static kv => kv.Value + ); /// /// Returns an http formatted content type string of a specified content type @@ -216,6 +197,18 @@ namespace VNLib.Net.Http /// of request, if unknown public static ContentType GetContentType(string type) => MimeToCt.GetValueOrDefault(type, ContentType.NonSupported); + /// + /// Returns the enum value from the MIME string + /// + /// Content type character span to compute the hashcode of + /// of request, if unknown + public static ContentType GetContentType(ReadOnlySpan type) + { + //Compute hashcode + int ctHashCode = string.GetHashCode(type, StringComparison.OrdinalIgnoreCase); + return ContentTypeHashLookup.GetValueOrDefault(ctHashCode, ContentType.NonSupported); + } + //Cache control string using mdn reference //https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control /// @@ -274,7 +267,6 @@ namespace VNLib.Net.Http /// /// Http acceptable method type string /// Request method, if method is malformatted or unsupported - /// public static HttpMethod GetRequestMethod(ReadOnlySpan smethod) { //Get the hashcode for the method "string" diff --git a/lib/Net.Http/src/Helpers/MimeLookups.cs b/lib/Net.Http/src/Helpers/MimeLookups.cs index 17582bb..c0dd82c 100644 --- a/lib/Net.Http/src/Helpers/MimeLookups.cs +++ b/lib/Net.Http/src/Helpers/MimeLookups.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -22,11 +22,8 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -using System; + using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace VNLib.Net.Http { @@ -3234,5 +3231,11 @@ namespace VNLib.Net.Http { "application/vnd.zul", ContentType.Zir }, { "application/vnd.handheld-entertainment+xml", ContentType.Zmm }, }; + + + /* + * A string hashcode lookup table for MIME content types + */ + private static readonly IReadOnlyDictionary ContentTypeHashLookup = ComputeCodeHashLookup(MimeToCt); } } -- cgit