diff options
Diffstat (limited to 'lib/Plugins.Essentials')
8 files changed, 77 insertions, 81 deletions
diff --git a/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs b/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs index 7c72bc4..048c543 100644 --- a/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs +++ b/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials @@ -42,6 +42,7 @@ namespace VNLib.Plugins.Essentials.Endpoints /// </summary> public abstract class ResourceEndpointBase : VirtualEndpoint<HttpEntity> { + /// <summary> /// Default protection settings. Protection settings are the most /// secure by default, should be loosened an necessary @@ -288,6 +289,11 @@ namespace VNLib.Plugins.Essentials.Endpoints /// <returns>The results of the processing</returns> protected virtual VfReturnType AlternateMethod(HttpEntity entity, HttpMethod method) => VirtualClose(entity, HttpStatusCode.MethodNotAllowed); + /// <summary> + /// This method gets invoked when an incoming OPTIONS request to the endpoint has been requested. + /// </summary> + /// <param name="entity">The entity to be processed</param> + /// <returns>The result of the operation to return to the file processor</returns> protected virtual VfReturnType Options(HttpEntity entity) => VfReturnType.Forbidden; /// <summary> @@ -328,7 +334,8 @@ namespace VNLib.Plugins.Essentials.Endpoints /// <param name="entity">The entity to close the connection for</param> /// <param name="jsonValue">A object that will be serialized and returned to the client as JSON</param> /// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns> - public static VfReturnType VirtualOkJson<T>(HttpEntity entity, T jsonValue) => VirtualCloseJson(entity, jsonValue, HttpStatusCode.OK); + public static VfReturnType VirtualOkJson<T>(HttpEntity entity, T jsonValue) + => VirtualCloseJson(entity, jsonValue, HttpStatusCode.OK); /// <summary> /// Shortcut helper methods to a virtual skip response with a 200 OK status code @@ -338,7 +345,8 @@ namespace VNLib.Plugins.Essentials.Endpoints /// <param name="webm">The <see cref="WebMessage"/> json response</param> /// <param name="code">The status code to return to the client</param> /// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns> - public static VfReturnType VirtualClose<T>(HttpEntity entity, T webm, HttpStatusCode code) where T: WebMessage => VirtualCloseJson(entity, webm, code); + public static VfReturnType VirtualClose<T>(HttpEntity entity, T webm, HttpStatusCode code) where T: WebMessage + => VirtualCloseJson(entity, webm, code); /// <summary> /// Shortcut helper methods to a virtual skip response with a given status code @@ -391,11 +399,10 @@ namespace VNLib.Plugins.Essentials.Endpoints /// <param name="code">The status code to return to the client</param> /// <param name="ct">The response content type</param> /// <param name="response">The stream response to return to the user</param> - /// <param name="length">The explicit length of the stream</param> /// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns> public static VfReturnType VirtualClose(HttpEntity entity, HttpStatusCode code, ContentType ct, Stream response) { - ArgumentNullException.ThrowIfNull(response, nameof(response)); + ArgumentNullException.ThrowIfNull(response); if (!response.CanSeek) { throw new IOException("The stream must be seekable when using implicit length"); @@ -405,6 +412,23 @@ namespace VNLib.Plugins.Essentials.Endpoints } /// <summary> + /// Shortcut helper methods to a virtual skip response with a given status code, + /// and memory content to return to the client + /// </summary> + /// <param name="entity">The entity to close the connection for</param> + /// <param name="code">The status code to return to the client</param> + /// <param name="ct">The response content type</param> + /// <param name="response">The stream response to return to the user</param> + /// <param name="length">The length of the response data to send to the clien</param> + /// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns> + public static VfReturnType VirtualClose(HttpEntity entity, HttpStatusCode code, ContentType ct, IHttpStreamResponse response, long length) + { + ArgumentNullException.ThrowIfNull(response); + entity.CloseResponse(code, ct, response, length); + return VfReturnType.VirtualSkip; + } + + /// <summary> /// Shortcut helper methods to a virtual skip response with a given status code, and /// a json payload to return to the client /// </summary> diff --git a/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs b/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs index 7a4364b..0d3623b 100644 --- a/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs +++ b/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials @@ -33,9 +33,7 @@ namespace VNLib.Plugins.Essentials.Endpoints public abstract class UnprotectedWebEndpoint : ResourceEndpointBase { ///<inheritdoc/> - protected override ERRNO PreProccess(HttpEntity entity) - { - return base.PreProccess(entity) && entity.Session.IsSet && entity.Session.SessionType == Sessions.SessionType.Web; - } + protected override ERRNO PreProccess(HttpEntity entity) + => base.PreProccess(entity) && entity.Session.IsSet && entity.Session.SessionType == Sessions.SessionType.Web; } }
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs b/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs index 4ffe288..6d42ca7 100644 --- a/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs +++ b/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials @@ -47,19 +47,21 @@ namespace VNLib.Plugins.Essentials.Endpoints /// <summary> /// Sets the log and path and checks the values /// </summary> - /// <param name="Path">The path this instance represents</param> + /// <param name="path">The path this instance represents</param> /// <param name="log">The log provider that will be used</param> /// <exception cref="ArgumentException"></exception> - protected void InitPathAndLog(string Path, ILogProvider log) + protected void InitPathAndLog(string path, ILogProvider log) { - if (string.IsNullOrWhiteSpace(Path) || Path[0] != '/') + ArgumentException.ThrowIfNullOrWhiteSpace(path); + ArgumentNullException.ThrowIfNull(log); + + if (path[0] != '/') { - throw new ArgumentException("Path must begin with a '/' character", nameof(Path)); + throw new ArgumentException("Path must begin with a '/' character", nameof(path)); } - //Store path - this.Path = Path; - //Store log - Log = log ?? throw new ArgumentNullException(nameof(log)); + + Path = path; + Log = log; } ///<inheritdoc/> diff --git a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs index 5f59346..8adf883 100644 --- a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs +++ b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs @@ -29,7 +29,6 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using VNLib.Net.Http; @@ -46,8 +45,7 @@ namespace VNLib.Plugins.Essentials.Extensions /// </summary> public static class EssentialHttpEventExtensions { - public const string BEARER_STRING = "Bearer"; - private static readonly int BEARER_LEN = BEARER_STRING.Length; + /* * Pooled/tlocal serializers @@ -798,31 +796,6 @@ namespace VNLib.Plugins.Essentials.Extensions //Parse the file using the specified parser return parser(file.FileData, file.ContentTypeString()); } - - /// <summary> - /// Gets the bearer token from an authorization header - /// </summary> - /// <param name="ci"></param> - /// <param name="token">The token stored in the user's authorization header</param> - /// <returns>True if the authorization header was set, has a Bearer token value</returns> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool HasAuthorization(this IConnectionInfo ci, [NotNullWhen(true)] out string? token) - { - ArgumentNullException.ThrowIfNull(ci); - - //Get auth header value - string? authorization = ci.Headers[HttpRequestHeader.Authorization]; - //Check if its set - if (!string.IsNullOrWhiteSpace(authorization)) - { - int bearerIndex = authorization.IndexOf(BEARER_STRING, StringComparison.OrdinalIgnoreCase); - //Calc token offset, get token, and trim any whitespace - token = authorization.AsSpan(bearerIndex + BEARER_LEN).Trim().ToString(); - return true; - } - token = null; - return false; - } /// <summary> /// Get a <see cref="DirectoryInfo"/> instance that points to the current sites filesystem root. diff --git a/lib/Plugins.Essentials/src/HttpEntity.cs b/lib/Plugins.Essentials/src/HttpEntity.cs index efdb2cd..2a24982 100644 --- a/lib/Plugins.Essentials/src/HttpEntity.cs +++ b/lib/Plugins.Essentials/src/HttpEntity.cs @@ -183,7 +183,7 @@ namespace VNLib.Plugins.Essentials public IReadOnlyList<FileUpload> Files => Entity.Files; ///<inheritdoc/> - HttpServer IHttpEvent.OriginServer => Entity.OriginServer; + IHttpServer IHttpEvent.OriginServer => Entity.OriginServer; /// <summary> /// Complete the session and respond to user diff --git a/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs b/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs index 3bce1f6..e65c26d 100644 --- a/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs +++ b/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials @@ -68,7 +68,7 @@ namespace VNLib.Plugins.Essentials.Oauth /// <summary> /// The request could not be processed at this time /// </summary> - TemporarilyUnabavailable + TemporarilyUnavailable } public static class OauthHttpExtensions @@ -114,7 +114,7 @@ namespace VNLib.Plugins.Essentials.Oauth case ErrorType.ServerError: writer.Append("server_error"); break; - case ErrorType.TemporarilyUnabavailable: + case ErrorType.TemporarilyUnavailable: writer.Append("temporarily_unavailable"); break; default: @@ -139,7 +139,7 @@ namespace VNLib.Plugins.Essentials.Oauth ErrorType.UnsupportedResponseType => "Bearer error=\"unsupported_response_type\"", ErrorType.InvalidScope => "Bearer error=\"invalid_scope\"", ErrorType.ServerError => "Bearer error=\"server_error\"", - ErrorType.TemporarilyUnabavailable => "Bearer error=\"temporarily_unavailable\"", + ErrorType.TemporarilyUnavailable => "Bearer error=\"temporarily_unavailable\"", ErrorType.InvalidClient => "Bearer error=\"invalid_client\"", ErrorType.InvalidToken => "Bearer error=\"invalid_token\"", _ => "Bearer error=\"error\"", diff --git a/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs b/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs index 823012e..d41350d 100644 --- a/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs +++ b/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Essentials @@ -22,7 +22,9 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ +using System; using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; using VNLib.Net.Http; @@ -35,59 +37,63 @@ namespace VNLib.Plugins.Essentials.Sessions /// <param name="event">The connection the session is attached to</param> /// <returns>A value task that resolves when the session has been released from the connection</returns> public delegate ValueTask SessionReleaseCallback(ISession session, IHttpEvent @event); - + /// <summary> /// A handle that holds exclusive access to a <see cref="ISession"/> /// session object /// </summary> - public readonly record struct SessionHandle + /// <param name="sessionData">The session data instance</param> + /// <param name="callback">A callback that is invoked when the handle is released</param> + /// <param name="entityStatus"></param> + public readonly struct SessionHandle(ISession? sessionData, FileProcessArgs entityStatus, SessionReleaseCallback? callback) : IEquatable<SessionHandle> { /// <summary> /// An empty <see cref="SessionHandle"/> instance. (A handle without a session object) /// </summary> public static readonly SessionHandle Empty = new(null, FileProcessArgs.Continue, null); - private readonly SessionReleaseCallback? ReleaseCb; - /// <summary> /// True when a valid session is held by the current handle /// </summary> - internal readonly bool IsSet => SessionData != null; + internal readonly bool IsSet { get; } = sessionData != null; /// <summary> /// The session data object associated with the current session /// </summary> - public readonly ISession? SessionData { get; } + public readonly ISession? SessionData => sessionData; /// <summary> /// A value indicating if the connection is valid and should continue to be processed /// </summary> - public readonly FileProcessArgs EntityStatus { get; } + public readonly FileProcessArgs EntityStatus => entityStatus; /// <summary> /// Initializes a new <see cref="SessionHandle"/> /// </summary> /// <param name="sessionData">The session data instance</param> /// <param name="callback">A callback that is invoked when the handle is released</param> - /// <param name="entityStatus"></param> - public SessionHandle(ISession? sessionData, FileProcessArgs entityStatus, SessionReleaseCallback? callback) - { - SessionData = sessionData; - ReleaseCb = callback; - EntityStatus = entityStatus; - } - /// <summary> - /// Initializes a new <see cref="SessionHandle"/> - /// </summary> - /// <param name="sessionData">The session data instance</param> - /// <param name="callback">A callback that is invoked when the handle is released</param> - public SessionHandle(ISession sessionData, SessionReleaseCallback callback):this(sessionData, FileProcessArgs.Continue, callback) + public SessionHandle(ISession sessionData, SessionReleaseCallback callback) : this(sessionData, FileProcessArgs.Continue, callback) {} /// <summary> /// Releases the session from use /// </summary> /// <param name="event">The current connection event object</param> - public readonly ValueTask ReleaseAsync(IHttpEvent @event) => ReleaseCb?.Invoke(SessionData!, @event) ?? ValueTask.CompletedTask; + public readonly ValueTask ReleaseAsync(IHttpEvent @event) => callback?.Invoke(SessionData!, @event) ?? ValueTask.CompletedTask; + + ///<inheritdoc/> + public override bool Equals([NotNullWhen(true)] object? obj) => obj is SessionHandle handle && Equals(handle); + + ///<inheritdoc/> + public bool Equals(SessionHandle other) => GetHashCode() == other.GetHashCode(); + + ///<inheritdoc/> + public override int GetHashCode() => HashCode.Combine(SessionData, EntityStatus, callback); + + ///<inheritdoc/> + public static bool operator ==(SessionHandle left, SessionHandle right) => left.Equals(right); + + ///<inheritdoc/> + public static bool operator !=(SessionHandle left, SessionHandle right) => !(left == right); } } diff --git a/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj b/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj index 9b8abb7..4da640a 100644 --- a/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj +++ b/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj @@ -25,13 +25,6 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance> </PropertyGroup> - - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> - <Deterministic>False</Deterministic> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> - <Deterministic>False</Deterministic> - </PropertyGroup> <ItemGroup> <PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2"> |