From 42ff77080d10b0fc9fecbbc46141e8e23a1d066a Mon Sep 17 00:00:00 2001 From: vnugent Date: Sat, 20 Apr 2024 00:45:57 -0400 Subject: fix!: Middlware array, multiple cookie set, and cookie check --- .../tests/VNLib.Hashing.PortableTests.csproj | 6 +-- .../VNLib.Net.CompressionTests.csproj | 6 +-- lib/Net.Http/src/Core/ConnectionInfo.cs | 3 +- lib/Net.Http/src/Core/HttpCookie.cs | 50 ++++++++++++---------- lib/Net.Http/src/Core/Response/HttpResponse.cs | 11 +++-- lib/Net.Http/src/Helpers/HttpHelpers.cs | 5 ++- .../src/Construction/SsBuilderExtensions.cs | 6 ++- .../src/PluginStackInitializer.cs | 2 +- .../src/Extensions/SingleCookieController.cs | 4 +- lib/Utils.Memory/vnlib_rpmalloc/Taskfile.yaml | 7 +-- lib/Utils.Memory/vnlib_rpmalloc/build.readme.txt | 2 +- lib/Utils.Memory/vnlib_rpmalloc/vnlib_rpmalloc.c | 3 ++ lib/Utils/tests/VNLib.UtilsTests.csproj | 6 +-- 13 files changed, 64 insertions(+), 47 deletions(-) (limited to 'lib') diff --git a/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj b/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj index db95906..1834464 100644 --- a/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj +++ b/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj @@ -15,9 +15,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive 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 fb462d1..24fc844 100644 --- a/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj +++ b/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/lib/Net.Http/src/Core/ConnectionInfo.cs b/lib/Net.Http/src/Core/ConnectionInfo.cs index 3af2b44..bcc5fe7 100644 --- a/lib/Net.Http/src/Core/ConnectionInfo.cs +++ b/lib/Net.Http/src/Core/ConnectionInfo.cs @@ -110,8 +110,9 @@ namespace VNLib.Net.Http Secure = secure | CrossOrigin, HttpOnly = httpOnly }; + //Set the cookie - Context.Response.AddCookie(cookie); + Context.Response.AddCookie(in cookie); } internal ConnectionInfo(HttpContext ctx) diff --git a/lib/Net.Http/src/Core/HttpCookie.cs b/lib/Net.Http/src/Core/HttpCookie.cs index e19aaec..b805e3e 100644 --- a/lib/Net.Http/src/Core/HttpCookie.cs +++ b/lib/Net.Http/src/Core/HttpCookie.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -30,44 +30,43 @@ using VNLib.Utils.Extensions; namespace VNLib.Net.Http.Core { - internal sealed class HttpCookie : IStringSerializeable, IEquatable + internal readonly struct HttpCookie(string name) : IStringSerializeable, IEquatable { - public string Name { get; } - public string? Value { get; init; } - public string? Domain { get; init; } - public string? Path { get; init; } - public TimeSpan MaxAge { get; init; } - public CookieSameSite SameSite { get; init; } - public bool Secure { get; init; } - public bool HttpOnly { get; init; } - public bool IsSession { get; init; } - - public HttpCookie(string name) => Name = name; - - public string Compile() - { - throw new NotImplementedException(); - } + public readonly string Name { get; } = name; + public readonly string? Value { get; init; } + public readonly string? Domain { get; init; } + public readonly string? Path { get; init; } + public readonly TimeSpan MaxAge { get; init; } + public readonly CookieSameSite SameSite { get; init; } + public readonly bool Secure { get; init; } + public readonly bool HttpOnly { get; init; } + public readonly bool IsSession { get; init; } + + public readonly string Compile() => throw new NotImplementedException(); - public void Compile(ref ForwardOnlyWriter writer) + public readonly void Compile(ref ForwardOnlyWriter writer) { //set the name of the cookie writer.Append(Name); writer.Append('='); + //set name writer.Append(Value); + //Only set the max age parameter if the cookie is not a session cookie if (!IsSession) { writer.Append("; Max-Age="); writer.Append((int)MaxAge.TotalSeconds); } + //Make sure domain is set if (!string.IsNullOrWhiteSpace(Domain)) { writer.Append("; Domain="); writer.Append(Domain); } + //Check and set path if (!string.IsNullOrWhiteSpace(Path)) { @@ -75,7 +74,9 @@ namespace VNLib.Net.Http.Core writer.Append("; Path="); writer.Append(Path); } + writer.Append("; SameSite="); + //Set the samesite flag based on the enum value switch (SameSite) { @@ -90,28 +91,31 @@ namespace VNLib.Net.Http.Core writer.Append("Lax"); break; } + //Set httponly flag if (HttpOnly) { writer.Append("; HttpOnly"); } + //Set secure flag if (Secure) { writer.Append("; Secure"); } } - public ERRNO Compile(Span buffer) + + public readonly ERRNO Compile(Span buffer) { ForwardOnlyWriter writer = new(buffer); Compile(ref writer); return writer.Written; } - public override int GetHashCode() => Name.GetHashCode(); + public readonly override int GetHashCode() => string.GetHashCode(Name, StringComparison.OrdinalIgnoreCase); - public override bool Equals(object? obj) => obj is HttpCookie other && Equals(other); + public readonly override bool Equals(object? obj) => obj is HttpCookie other && Equals(other); - public bool Equals(HttpCookie? other) => other != null && Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase); + public readonly bool Equals(HttpCookie other) => Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase); } } \ No newline at end of file diff --git a/lib/Net.Http/src/Core/Response/HttpResponse.cs b/lib/Net.Http/src/Core/Response/HttpResponse.cs index 06f114c..1340dac 100644 --- a/lib/Net.Http/src/Core/Response/HttpResponse.cs +++ b/lib/Net.Http/src/Core/Response/HttpResponse.cs @@ -44,7 +44,9 @@ namespace VNLib.Net.Http.Core.Response , IStringSerializeable #endif { - private readonly HashSet Cookies = []; + const int DefaultCookieCapacity = 2; + + private readonly Dictionary Cookies = new(DefaultCookieCapacity, StringComparer.OrdinalIgnoreCase); private readonly DirectStream ReusableDirectStream = new(); private readonly ChunkedStream ReusableChunkedStream = new(manager.ChunkAccumulatorBuffer, ContextInfo); private readonly HeaderDataAccumulator Writer = new(manager.ResponseHeaderBuffer, ContextInfo); @@ -86,7 +88,7 @@ namespace VNLib.Net.Http.Core.Response /// /// Cookie to add [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void AddCookie(HttpCookie cookie) => Cookies.Add(cookie); + internal void AddCookie(in HttpCookie cookie) => Cookies[cookie.Name] = cookie; /// /// Compiles and flushes all headers to the header accumulator ready for sending @@ -132,7 +134,7 @@ namespace VNLib.Net.Http.Core.Response //Write cookies if any are set if (Cookies.Count > 0) { - foreach (HttpCookie cookie in Cookies) + foreach (HttpCookie cookie in Cookies.Values) { writer.Append("Set-Cookie: "); @@ -298,6 +300,7 @@ namespace VNLib.Net.Http.Core.Response { ReusableChunkedStream.OnRelease(); ReusableDirectStream.OnRelease(); + Cookies.TrimExcess(DefaultCookieCapacity); } /// @@ -428,7 +431,7 @@ namespace VNLib.Net.Http.Core.Response } //Enumerate and write - foreach (HttpCookie cookie in Cookies) + foreach (HttpCookie cookie in Cookies.Values) { writer.Append("Set-Cookie: "); diff --git a/lib/Net.Http/src/Helpers/HttpHelpers.cs b/lib/Net.Http/src/Helpers/HttpHelpers.cs index 86511a5..86616f8 100644 --- a/lib/Net.Http/src/Helpers/HttpHelpers.cs +++ b/lib/Net.Http/src/Helpers/HttpHelpers.cs @@ -172,7 +172,7 @@ namespace VNLib.Net.Http return ComputeCodeHashLookup( Enum.GetValues() //Exclude the not supported method - .Except(new HttpMethod[] { HttpMethod.None }) + .Except([ HttpMethod.None ]) .Select(m => KeyValuePair.Create(m.ToString(), m)) ).ToFrozenDictionary(); } @@ -284,6 +284,9 @@ namespace VNLib.Net.Http /// True if first 2 bytes of each address match (Big Endian) public static bool IsLocalSubnet(this IPAddress first, IPAddress other) { + ArgumentNullException.ThrowIfNull(first); + ArgumentNullException.ThrowIfNull(other); + if(first.AddressFamily != other.AddressFamily) { return false; diff --git a/lib/Plugins.Essentials.ServiceStack/src/Construction/SsBuilderExtensions.cs b/lib/Plugins.Essentials.ServiceStack/src/Construction/SsBuilderExtensions.cs index 5512e49..4195553 100644 --- a/lib/Plugins.Essentials.ServiceStack/src/Construction/SsBuilderExtensions.cs +++ b/lib/Plugins.Essentials.ServiceStack/src/Construction/SsBuilderExtensions.cs @@ -285,7 +285,8 @@ namespace VNLib.Plugins.Essentials.ServiceStack.Construction Instance.AddServices(plugin.Services); //Add all exposed middleware to the chain - plugin.OnPluginServiceEvent>(p => p.TryForeach(Instance.Options.MiddlewareChain.Add)); + plugin.OnPluginServiceEvent>(p => p.ForEach(Instance.Options.MiddlewareChain.Add)); + plugin.OnPluginServiceEvent(p => p.ForEach(Instance.Options.MiddlewareChain.Add)); } /// @@ -296,7 +297,8 @@ namespace VNLib.Plugins.Essentials.ServiceStack.Construction Instance.RemoveServices(plugin.Services); //Remove all middleware from the chain - plugin.OnPluginServiceEvent>(p => p.TryForeach(Instance.Options.MiddlewareChain.Remove)); + plugin.OnPluginServiceEvent>(p => p.ForEach(Instance.Options.MiddlewareChain.Remove)); + plugin.OnPluginServiceEvent(p => p.ForEach(Instance.Options.MiddlewareChain.Remove)); } } diff --git a/lib/Plugins.Essentials.ServiceStack/src/PluginStackInitializer.cs b/lib/Plugins.Essentials.ServiceStack/src/PluginStackInitializer.cs index 5a33425..5f4e6e0 100644 --- a/lib/Plugins.Essentials.ServiceStack/src/PluginStackInitializer.cs +++ b/lib/Plugins.Essentials.ServiceStack/src/PluginStackInitializer.cs @@ -273,7 +273,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack public void Load() { Plugin.Load(); - Plugin.GetAllExportedServices(Services); + Plugin.GetAllExportedServices(_container); //Finally notify of load Listener.OnPluginLoaded(this); diff --git a/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs b/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs index 2d41e4c..f3b02dc 100644 --- a/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs +++ b/lib/Plugins.Essentials/src/Extensions/SingleCookieController.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials @@ -92,7 +92,7 @@ namespace VNLib.Plugins.Essentials.Extensions private void SetCookieInternal(IHttpEvent entity, string value, bool force) { //Only set cooke if already exists or force is true - if (entity.Server.RequestCookies.ContainsKey(value) || force) + if (entity.Server.RequestCookies.ContainsKey(Name) || force) { //Build and set cookie HttpCookie cookie = new(Name, value) diff --git a/lib/Utils.Memory/vnlib_rpmalloc/Taskfile.yaml b/lib/Utils.Memory/vnlib_rpmalloc/Taskfile.yaml index b9d5d70..b327913 100644 --- a/lib/Utils.Memory/vnlib_rpmalloc/Taskfile.yaml +++ b/lib/Utils.Memory/vnlib_rpmalloc/Taskfile.yaml @@ -10,7 +10,6 @@ version: '3' vars: PROJECT_NAME: 'vnlib_rpmalloc' - MODULE_NAME: 'vnlib.core' tasks: @@ -18,8 +17,10 @@ tasks: desc: "Builds the entire project from source code without using the VNBuild build system for target machines" cmds: #build with defaults - - task: build - - cmd: echo "Your vnlib_rpmalloc dll file can be found in '{{.USER_WORKING_DIR}}/build'" + #init cmake build with greedy enabled + - cmake -Bbuild/ -DCMAKE_BUILD_TYPE=Release -DENABLE_GREEDY=1 + - cmake --build build/ --config Release + - cmd: echo "Your vnlib_rpmalloc library file can be found in '{{.USER_WORKING_DIR}}/build'" silent: true build: diff --git a/lib/Utils.Memory/vnlib_rpmalloc/build.readme.txt b/lib/Utils.Memory/vnlib_rpmalloc/build.readme.txt index 77f2193..79a7091 100644 --- a/lib/Utils.Memory/vnlib_rpmalloc/build.readme.txt +++ b/lib/Utils.Memory/vnlib_rpmalloc/build.readme.txt @@ -1,4 +1,4 @@ -vnlib_rpmalloc Copyright (C) 2023 Vaughn Nugent +vnlib_rpmalloc Copyright (C) 2024 Vaughn Nugent vnlib_rpmalloc is a wrapper library for rpmalloc by Mattias Jansson that implements the NativeHeapApi functions, and exports them by default for use as a library. The CMake configuration is setup to produce both diff --git a/lib/Utils.Memory/vnlib_rpmalloc/vnlib_rpmalloc.c b/lib/Utils.Memory/vnlib_rpmalloc/vnlib_rpmalloc.c index 2b63dcc..c1a836b 100644 --- a/lib/Utils.Memory/vnlib_rpmalloc/vnlib_rpmalloc.c +++ b/lib/Utils.Memory/vnlib_rpmalloc/vnlib_rpmalloc.c @@ -134,7 +134,10 @@ int pthread_create(pthread_t* thread, thread_starter_arg* starter_arg = rpmalloc(sizeof(thread_starter_arg)); starter_arg->real_start = start_routine; starter_arg->real_arg = arg; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" return (*(int (*)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*))real_pthread_create)(thread, attr, thread_starter, starter_arg); +#pragma GCC diagnostic pop } #endif diff --git a/lib/Utils/tests/VNLib.UtilsTests.csproj b/lib/Utils/tests/VNLib.UtilsTests.csproj index 9a8891e..83013ff 100644 --- a/lib/Utils/tests/VNLib.UtilsTests.csproj +++ b/lib/Utils/tests/VNLib.UtilsTests.csproj @@ -17,9 +17,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive -- cgit