aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-08-05 00:52:48 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-08-05 00:52:48 -0400
commit46c6450fdc9b62aa04bae545b03d93a2e8c8895a (patch)
treec5648e1ce68acd28cb29807ba65d90af3ba1caef /lib
parenta3ded6043a926735142f3bb48093e83135044c06 (diff)
Response compression buffer patch
Diffstat (limited to 'lib')
-rw-r--r--lib/Hashing.Portable/src/IdentityUtility/JwtPayload.cs (renamed from lib/Hashing.Portable/src/IdentityUtility/JwtClaim.cs)4
-rw-r--r--lib/Net.Compression/VNLib.Net.Compression/CompressorManager.cs9
-rw-r--r--lib/Net.Compression/vnlib_compress/compression.c17
-rw-r--r--lib/Net.Compression/vnlib_compress/compression.h6
-rw-r--r--lib/Net.Compression/vnlib_compress/util.h7
-rw-r--r--lib/Net.Http/src/Core/ConnectionInfo.cs59
-rw-r--r--lib/Net.Http/src/Core/Response/ResponseWriter.cs6
-rw-r--r--lib/Net.Http/src/IConnectionInfo.cs19
-rw-r--r--lib/Net.Rest.Client/src/Construction/Extensions.cs87
-rw-r--r--lib/Plugins.Essentials/src/Accounts/AccountUtils.cs2
-rw-r--r--lib/Plugins.Essentials/src/EventProcessor.cs81
-rw-r--r--lib/Plugins.Essentials/src/Extensions/ConnectionInfoExtensions.cs65
-rw-r--r--lib/Plugins.Essentials/src/Oauth/IOAuth2Provider.cs44
-rw-r--r--lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs18
-rw-r--r--lib/Plugins.Essentials/src/Oauth/OauthSessionCacheExhaustedException.cs43
-rw-r--r--lib/Plugins.Essentials/src/Sessions/SessionBase.cs4
16 files changed, 235 insertions, 236 deletions
diff --git a/lib/Hashing.Portable/src/IdentityUtility/JwtClaim.cs b/lib/Hashing.Portable/src/IdentityUtility/JwtPayload.cs
index be8c682..eb33e00 100644
--- a/lib/Hashing.Portable/src/IdentityUtility/JwtClaim.cs
+++ b/lib/Hashing.Portable/src/IdentityUtility/JwtPayload.cs
@@ -3,9 +3,9 @@
*
* Library: VNLib
* Package: VNLib.Hashing.Portable
-* File: JwtClaim.cs
+* File: JwtPayload.cs
*
-* JwtClaim.cs is part of VNLib.Hashing.Portable which is part of the larger
+* JwtPayload.cs is part of VNLib.Hashing.Portable which is part of the larger
* VNLib collection of libraries and utilities.
*
* VNLib.Hashing.Portable is free software: you can redistribute it and/or modify
diff --git a/lib/Net.Compression/VNLib.Net.Compression/CompressorManager.cs b/lib/Net.Compression/VNLib.Net.Compression/CompressorManager.cs
index af77329..0695791 100644
--- a/lib/Net.Compression/VNLib.Net.Compression/CompressorManager.cs
+++ b/lib/Net.Compression/VNLib.Net.Compression/CompressorManager.cs
@@ -36,9 +36,9 @@
using System;
using System.Buffers;
+using System.Text.Json;
using System.Diagnostics;
using System.IO.Compression;
-using System.Text.Json;
using System.Runtime.CompilerServices;
using VNLib.Net.Http;
@@ -170,13 +170,6 @@ namespace VNLib.Net.Compression
throw new InvalidOperationException("This compressor instance has not been initialized, cannot free compressor");
}
- /*
- * We only alloc the buffer on the first call because we can assume this is the
- * largest input data the compressor will see, and the block size should be used
- * as a reference for callers. If its too small it will just have to be flushed
- */
-
-
//Compress the block
return CompressBlock(compressor.Instance, output, input, false);
}
diff --git a/lib/Net.Compression/vnlib_compress/compression.c b/lib/Net.Compression/vnlib_compress/compression.c
index 0e563ff..959540d 100644
--- a/lib/Net.Compression/vnlib_compress/compression.c
+++ b/lib/Net.Compression/vnlib_compress/compression.c
@@ -63,11 +63,11 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
VNLIB_EXPORT CompressorType VNLIB_CC GetSupportedCompressors(void);
-VNLIB_EXPORT int VNLIB_CC GetCompressorBlockSize(void* compressor);
+VNLIB_EXPORT int VNLIB_CC GetCompressorBlockSize(_In_ void* compressor);
-VNLIB_EXPORT CompressorType VNLIB_CC GetCompressorType(void* compressor);
+VNLIB_EXPORT CompressorType VNLIB_CC GetCompressorType(_In_ void* compressor);
-VNLIB_EXPORT CompressionLevel VNLIB_CC GetCompressorLevel(void* compressor);
+VNLIB_EXPORT CompressionLevel VNLIB_CC GetCompressorLevel(_In_ void* compressor);
VNLIB_EXPORT void* VNLIB_CC AllocateCompressor(CompressorType type, CompressionLevel level);
@@ -106,7 +106,7 @@ VNLIB_EXPORT CompressorType VNLIB_CC GetSupportedCompressors(void)
return supported;
}
-VNLIB_EXPORT CompressorType VNLIB_CC GetCompressorType(void* compressor)
+VNLIB_EXPORT CompressorType VNLIB_CC GetCompressorType(_In_ void* compressor)
{
if (!compressor)
{
@@ -116,7 +116,7 @@ VNLIB_EXPORT CompressorType VNLIB_CC GetCompressorType(void* compressor)
return ((CompressorState*)compressor)->type;
}
-VNLIB_EXPORT CompressionLevel VNLIB_CC GetCompressorLevel(void* compressor)
+VNLIB_EXPORT CompressionLevel VNLIB_CC GetCompressorLevel(_In_ void* compressor)
{
if (!compressor)
{
@@ -126,7 +126,7 @@ VNLIB_EXPORT CompressionLevel VNLIB_CC GetCompressorLevel(void* compressor)
return ((CompressorState*)compressor)->level;
}
-VNLIB_EXPORT int VNLIB_CC GetCompressorBlockSize(void* compressor)
+VNLIB_EXPORT int VNLIB_CC GetCompressorBlockSize(_In_ void* compressor)
{
if (!compressor)
{
@@ -195,7 +195,6 @@ VNLIB_EXPORT void* VNLIB_CC AllocateCompressor(CompressorType type, CompressionL
}
-
/*
If result was successfull return the context pointer, if
the creation failed, free the state if it was allocated
@@ -290,7 +289,7 @@ VNLIB_EXPORT int VNLIB_CC FreeCompressor(void* compressor)
return errorCode;
}
-VNLIB_EXPORT int VNLIB_CC GetCompressedSize(void* compressor, int inputLength, int flush)
+VNLIB_EXPORT int VNLIB_CC GetCompressedSize(_In_ void* compressor, int inputLength, int flush)
{
CompressorState* comp;
int result;
@@ -343,7 +342,7 @@ VNLIB_EXPORT int VNLIB_CC GetCompressedSize(void* compressor, int inputLength, i
* indicate failure.
* @param compressor
*/
-VNLIB_EXPORT int VNLIB_CC CompressBlock(void* compressor, CompressionOperation* operation)
+VNLIB_EXPORT int VNLIB_CC CompressBlock(_In_ void* compressor, CompressionOperation* operation)
{
int result;
CompressorState* comp;
diff --git a/lib/Net.Compression/vnlib_compress/compression.h b/lib/Net.Compression/vnlib_compress/compression.h
index 153b7fc..930ef1c 100644
--- a/lib/Net.Compression/vnlib_compress/compression.h
+++ b/lib/Net.Compression/vnlib_compress/compression.h
@@ -40,8 +40,6 @@
#include "util.h"
#include <stdint.h>
-#include <stddef.h>
-#include <stdlib.h>
#define ERR_COMP_TYPE_NOT_SUPPORTED -9
#define ERR_COMP_LEVEL_NOT_SUPPORTED -10
@@ -140,13 +138,13 @@ typedef struct CompressionOperationStruct {
/*
* Input stream data
*/
- const uint8_t* bytesIn;
+ const void* bytesIn;
const int bytesInLength;
/*
* Output buffer/data stream
*/
- uint8_t* bytesOut;
+ void* bytesOut;
const int bytesOutLength;
/*
diff --git a/lib/Net.Compression/vnlib_compress/util.h b/lib/Net.Compression/vnlib_compress/util.h
index 6e7b59e..583e10b 100644
--- a/lib/Net.Compression/vnlib_compress/util.h
+++ b/lib/Net.Compression/vnlib_compress/util.h
@@ -24,6 +24,8 @@
#ifndef UTIL_H_
#define UTIL_H_
+#include <stdlib.h>
+
/*
* Stub missing types and constants for GCC
*/
@@ -46,6 +48,11 @@
#define NULL 0
#endif /* !NULL */
+#ifndef _In_
+#define _In_
+#endif // !_In_
+
+
/*
* Stub method for malloc. All calls to vnmalloc should be freed with vnfree.
*/
diff --git a/lib/Net.Http/src/Core/ConnectionInfo.cs b/lib/Net.Http/src/Core/ConnectionInfo.cs
index e680152..8a1525c 100644
--- a/lib/Net.Http/src/Core/ConnectionInfo.cs
+++ b/lib/Net.Http/src/Core/ConnectionInfo.cs
@@ -24,13 +24,11 @@
using System;
using System.Net;
-using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Security.Authentication;
using VNLib.Net.Http.Core;
-using VNLib.Utils.Extensions;
namespace VNLib.Net.Http
{
@@ -76,65 +74,16 @@ namespace VNLib.Net.Http
///<inheritdoc/>
public IReadOnlyDictionary<string, string> RequestCookies => Context.Request.Cookies;
///<inheritdoc/>
- public IEnumerable<string> Accept => Context.Request.Accept;
+ public IReadOnlyCollection<string> Accept => Context.Request.Accept;
///<inheritdoc/>
public TransportSecurityInfo? TransportSecurity => Context.GetSecurityInfo();
///<inheritdoc/>
- public bool Accepts(ContentType type)
- {
- //Get the content type string from he specified content type
- string contentType = HttpHelpers.GetContentTypeString(type);
- return Accepts(contentType);
- }
-
- ///<inheritdoc/>
- public bool Accepts(string contentType)
- {
- if (AcceptsAny())
- {
- return true;
- }
-
- //If client accepts exact requested encoding
- if (Accept.Contains(contentType, StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
-
- //Search for the content-sub-type
-
- //Get prinary side of mime type
- ReadOnlySpan<char> primary = contentType.AsSpan().SliceBeforeParam('/');
-
- for (int i = 0; i < Context.Request.Accept.Count; i++)
- {
- //The the accept subtype
- ReadOnlySpan<char> ctSubType = Context.Request.Accept[i].AsSpan().SliceBeforeParam('/');
-
- //See if accepts any subtype, or the primary sub-type matches
- if(ctSubType[0] == '*' || ctSubType.Equals(primary, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
- return false;
- }
-
- /// <summary>
- /// Determines if the connection accepts any content type
- /// </summary>
- /// <returns>true if the connection accepts any content typ, false otherwise</returns>
- private bool AcceptsAny()
- {
- //Accept any if no accept header was present, or accept all value */*
- return Context.Request.Accept.Count == 0 || Accept.Where(static t => t.StartsWith("*/*", StringComparison.OrdinalIgnoreCase)).Any();
- }
-
- ///<inheritdoc/>
public void SetCookie(string name, string value, string? domain, string? path, TimeSpan Expires, CookieSameSite sameSite, bool httpOnly, bool secure)
{
+ //name MUST not be null
+ _ = name ?? throw new ArgumentNullException(nameof(name));
+
//Create the new cookie
HttpCookie cookie = new(name)
{
diff --git a/lib/Net.Http/src/Core/Response/ResponseWriter.cs b/lib/Net.Http/src/Core/Response/ResponseWriter.cs
index d67fc01..dcb220f 100644
--- a/lib/Net.Http/src/Core/Response/ResponseWriter.cs
+++ b/lib/Net.Http/src/Core/Response/ResponseWriter.cs
@@ -242,7 +242,7 @@ namespace VNLib.Net.Http.Core
}
//Compress the buffered data and flush if required
- if(CompressNextSegment(buffer, comp, writer))
+ if (CompressNextSegment(buffer, read, comp, writer))
{
//Time to flush
await writer.FlushAsync(false);
@@ -309,13 +309,13 @@ namespace VNLib.Net.Http.Core
return writer.Advance(res.BytesWritten) == 0;
}
- private static bool CompressNextSegment(Memory<byte> readSegment, IResponseCompressor comp, IResponseDataWriter writer)
+ private static bool CompressNextSegment(Memory<byte> readSegment, int read, IResponseCompressor comp, IResponseDataWriter writer)
{
//Get output buffer
Memory<byte> output = writer.GetMemory();
//Compress the trimmed block
- CompressionResult res = comp.CompressBlock(readSegment, output);
+ CompressionResult res = comp.CompressBlock(readSegment[..read], output);
return writer.Advance(res.BytesWritten) == 0;
}
diff --git a/lib/Net.Http/src/IConnectionInfo.cs b/lib/Net.Http/src/IConnectionInfo.cs
index 17ee16f..0feedd9 100644
--- a/lib/Net.Http/src/IConnectionInfo.cs
+++ b/lib/Net.Http/src/IConnectionInfo.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -113,25 +113,12 @@ namespace VNLib.Net.Http
/// <summary>
/// Gets an <see cref="IEnumerator{T}"/> for the parsed accept header values
/// </summary>
- IEnumerable<string> Accept { get; }
+ IReadOnlyCollection<string> Accept { get; }
/// <summary>
/// Gets the underlying transport security information for the current connection
/// </summary>
TransportSecurityInfo? TransportSecurity { get; }
-
- /// <summary>
- /// Determines if the client accepts the response content type
- /// </summary>
- /// <param name="type">The desired content type</param>
- /// <returns>True if the client accepts the content type, false otherwise</returns>
- bool Accepts(ContentType type);
-
- /// <summary>
- /// Determines if the client accepts the response content type
- /// </summary>
- /// <param name="contentType">The desired content type</param>
- /// <returns>True if the client accepts the content type, false otherwise</returns>
- bool Accepts(string contentType);
+
/// <summary>
/// Adds a new cookie to the response. If a cookie with the same name and value
diff --git a/lib/Net.Rest.Client/src/Construction/Extensions.cs b/lib/Net.Rest.Client/src/Construction/Extensions.cs
index 52a1301..bbc8b1d 100644
--- a/lib/Net.Rest.Client/src/Construction/Extensions.cs
+++ b/lib/Net.Rest.Client/src/Construction/Extensions.cs
@@ -153,6 +153,21 @@ namespace VNLib.Net.Rest.Client.Construction
}
/// <summary>
+ /// Sets a callback that will create a query string argument value
+ /// </summary>
+ /// <typeparam name="TModel">The request entity type</typeparam>
+ /// <param name="builder"></param>
+ /// <param name="value">The constant query value</param>
+ /// <param name="parameter">The name of the query paramter to set</param>
+ /// <returns>The chainable <see cref="IRestRequestBuilder{TModel}"/></returns>
+ public static IRestRequestBuilder<TModel> WithQuery<TModel>(this IRestRequestBuilder<TModel> builder, string parameter, string value)
+ {
+ //Get a query item string value from the callback and sets the query paremter
+ builder.WithModifier((m, r) => r.AddQueryParameter(parameter, value));
+ return builder;
+ }
+
+ /// <summary>
/// Specifies a model that will handle its own request body builder
/// </summary>
/// <typeparam name="TModel"></typeparam>
@@ -182,6 +197,18 @@ namespace VNLib.Net.Rest.Client.Construction
}
/// <summary>
+ /// Allows building of a single endpoint from an <see cref="IRestEndpointDefinition"/> and stores it in the
+ /// adapter store.
+ /// </summary>
+ /// <param name="site"></param>
+ /// <returns>A chainable <see cref="IRestEndpointBuilder"/> to build the endpoint</returns>
+ public static IRestEndpointBuilder DefineSingleEndpoint(this IRestSiteEndpointStore site)
+ {
+ EndpointAdapterBuilder builder = new(site);
+ return builder;
+ }
+
+ /// <summary>
/// Sets the uri for all new request messages
/// </summary>
/// <typeparam name="TModel">The request entity type</typeparam>
@@ -195,6 +222,35 @@ namespace VNLib.Net.Rest.Client.Construction
return builder;
}
+
+ /// <summary>
+ /// Sets the uri for all new request messages
+ /// </summary>
+ /// <typeparam name="TModel">The request entity type</typeparam>
+ /// <param name="builder"></param>
+ /// <param name="uri">Specifies the uri for the request builder</param>
+ /// <returns>The chainable <see cref="IRestRequestBuilder{TModel}"/></returns>
+ public static IRestRequestBuilder<TModel> WithUrl<TModel>(this IRestRequestBuilder<TModel> builder, Uri uri)
+ {
+ //Use the supplied method to convert the uri to a string
+ builder.WithUrl((m) => uri.ToString());
+ return builder;
+ }
+
+ /// <summary>
+ /// Sets the uri for all new request messages
+ /// </summary>
+ /// <typeparam name="TModel">The request entity type</typeparam>
+ /// <param name="builder"></param>
+ /// <param name="url">Specifies the uri for the request builder</param>
+ /// <returns>The chainable <see cref="IRestRequestBuilder{TModel}"/></returns>
+ public static IRestRequestBuilder<TModel> WithUrl<TModel>(this IRestRequestBuilder<TModel> builder, string url)
+ {
+ //Use the supplied method to convert the uri to a string
+ builder.WithUrl((m) => url);
+ return builder;
+ }
+
/// <summary>
/// Specifies a connection header to set for every request
/// </summary>
@@ -226,6 +282,37 @@ namespace VNLib.Net.Rest.Client.Construction
}
/// <summary>
+ /// Sets a callback that will create a parameter string argument value
+ /// </summary>
+ /// <typeparam name="TModel">The request entity type</typeparam>
+ /// <param name="builder"></param>
+ /// <param name="callback">The callback method that gets the query value</param>
+ /// <param name="parameter">The body paramter value to set</param>
+ /// <returns>The chainable <see cref="IRestRequestBuilder{TModel}"/></returns>
+ public static IRestRequestBuilder<TModel> WithParameter<TModel>(this IRestRequestBuilder<TModel> builder, string parameter, Func<TModel, string> callback)
+ {
+ //Get a query item string value from the callback and sets the query paremter
+ builder.WithModifier((m, r) => r.AddParameter(parameter, callback(m), ParameterType.GetOrPost));
+ return builder;
+ }
+
+ /// <summary>
+ /// Sets a constant parameter string argument value
+ /// </summary>
+ /// <typeparam name="TModel">The request entity type</typeparam>
+ /// <param name="builder"></param>
+ /// <param name="value">The constant value</param>
+ /// <param name="parameter">The query paramter value to set</param>
+ /// <returns>The chainable <see cref="IRestRequestBuilder{TModel}"/></returns>
+ public static IRestRequestBuilder<TModel> WithParameter<TModel>(this IRestRequestBuilder<TModel> builder, string parameter, string value)
+ {
+ //Get a query item string value from the callback and sets the query paremter
+ builder.WithModifier((m, r) => r.AddParameter(parameter, value, ParameterType.GetOrPost));
+ return builder;
+ }
+
+
+ /// <summary>
/// Converts a task that resolves a <see cref="RestResponse"/> to a task that deserializes
/// the response data as json.
/// </summary>
diff --git a/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs b/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs
index 33da10e..137fa4a 100644
--- a/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs
+++ b/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs
@@ -320,7 +320,7 @@ namespace VNLib.Plugins.Essentials.Accounts
//Get the "local" account flag from the user object
bool localAccount = user.IsLocalAccount();
- //Set local account flag
+ //Set local account flag on the session
entity.Session.HasLocalAccount(localAccount);
//Return the client encrypted data
diff --git a/lib/Plugins.Essentials/src/EventProcessor.cs b/lib/Plugins.Essentials/src/EventProcessor.cs
index a207e35..bd4383f 100644
--- a/lib/Plugins.Essentials/src/EventProcessor.cs
+++ b/lib/Plugins.Essentials/src/EventProcessor.cs
@@ -35,10 +35,10 @@ using VNLib.Net.Http;
using VNLib.Utils.IO;
using VNLib.Utils.Logging;
using VNLib.Utils.Resources;
+using VNLib.Plugins.Essentials.Accounts;
using VNLib.Plugins.Essentials.Content;
using VNLib.Plugins.Essentials.Sessions;
using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Plugins.Essentials.Accounts;
#nullable enable
@@ -163,12 +163,10 @@ namespace VNLib.Plugins.Essentials
* Wrapper class for converting IHttpEvent endpoints to
* httpEntityEndpoints
*/
- private sealed class EvEndpointWrapper : IVirtualEndpoint<HttpEntity>
+ private sealed record class EvEndpointWrapper(IVirtualEndpoint<IHttpEvent> Wrapped) : IVirtualEndpoint<HttpEntity>
{
- private readonly IVirtualEndpoint<IHttpEvent> _wrapped;
- public EvEndpointWrapper(IVirtualEndpoint<IHttpEvent> wrapping) => _wrapped = wrapping;
- string IEndpoint.Path => _wrapped.Path;
- ValueTask<VfReturnType> IVirtualEndpoint<HttpEntity>.Process(HttpEntity entity) => _wrapped.Process(entity);
+ string IEndpoint.Path => Wrapped.Path;
+ ValueTask<VfReturnType> IVirtualEndpoint<HttpEntity>.Process(HttpEntity entity) => Wrapped.Process(entity);
}
@@ -318,6 +316,8 @@ namespace VNLib.Plugins.Essentials
//Start cancellation token
CancellationTokenSource timeout = new(Options.ExecutionTimeout);
+ FileProcessArgs args;
+
try
{
//Session handle, default to the shared empty session
@@ -341,24 +341,35 @@ namespace VNLib.Plugins.Essentials
HttpEntity entity = new(httpEvent, this, in sessionHandle, timeout.Token);
//Pre-process entity
- FileProcessArgs preProc = await PreProcessEntityAsync(entity);
+ args = await PreProcessEntityAsync(entity);
//If preprocess returned a value, exit
- if (preProc != FileProcessArgs.Continue)
+ if (args != FileProcessArgs.Continue)
{
- ProcessFile(httpEvent, in preProc);
+ ProcessFile(httpEvent, in args);
return;
}
if (VirtualEndpoints.Count > 0)
{
- //Process a virtual file
- FileProcessArgs virtualArgs = await ProcessVirtualAsync(entity);
+ //See if the virtual file is servicable
+ if (!VirtualEndpoints.TryGetValue(entity.Server.Path, out IVirtualEndpoint<HttpEntity>? vf))
+ {
+ args = FileProcessArgs.Continue;
+ }
+ else
+ {
+ //Invoke the page handler process method
+ VfReturnType rt = await vf.Process(entity);
+
+ //Process a virtual file
+ args = GetArgsFromReturn(entity, rt);
+ }
//If the entity was processed, exit
- if (virtualArgs != FileProcessArgs.Continue)
+ if (args != FileProcessArgs.Continue)
{
- ProcessFile(httpEvent, in virtualArgs);
+ ProcessFile(httpEvent, in args);
return;
}
}
@@ -371,7 +382,7 @@ namespace VNLib.Plugins.Essentials
}
//Finally process as file
- FileProcessArgs args = await RouteFileAsync(entity);
+ args = await RouteFileAsync(entity);
//Finally process the file
ProcessFile(httpEvent, in args);
@@ -582,38 +593,29 @@ namespace VNLib.Plugins.Essentials
}
}
-
/// <summary>
- /// If virtual endpoints are enabled, checks for the existance of an
- /// endpoint and attmepts to process that endpoint.
+ /// Gets the <see cref="FileProcessArgs"/> that will finalize the response from the
+ /// given <see cref="VfReturnType"/>
/// </summary>
- /// <param name="entity">The http entity to proccess</param>
- /// <returns>The results to return to the file processor, or null of the entity requires further processing</returns>
- protected virtual async ValueTask<FileProcessArgs> ProcessVirtualAsync(HttpEntity entity)
+ /// <param name="entity">The entity to be processed</param>
+ /// <param name="returnType">The virtual file processor return type</param>
+ /// <returns>The process args to end processing for the virtual endpoint</returns>
+ protected virtual FileProcessArgs GetArgsFromReturn(HttpEntity entity, VfReturnType returnType)
{
- //See if the virtual file is servicable
- if (!VirtualEndpoints.TryGetValue(entity.Server.Path, out IVirtualEndpoint<HttpEntity>? vf))
- {
- return FileProcessArgs.Continue;
- }
-
- //Invoke the page handler process method
- VfReturnType rt = await vf.Process(entity);
-
- if (rt == VfReturnType.VirtualSkip)
+ if (returnType == VfReturnType.VirtualSkip)
{
//Virtual file was handled by the handler
return FileProcessArgs.VirtualSkip;
}
- else if(rt == VfReturnType.ProcessAsFile)
+ else if (returnType == VfReturnType.ProcessAsFile)
{
return FileProcessArgs.Continue;
}
-
+
//If not a get request, process it directly
if (entity.Server.Method == HttpMethod.GET)
{
- switch (rt)
+ switch (returnType)
{
case VfReturnType.Forbidden:
return FileProcessArgs.Deny;
@@ -625,8 +627,8 @@ namespace VNLib.Plugins.Essentials
break;
}
}
-
- switch (rt)
+
+ switch (returnType)
{
case VfReturnType.Forbidden:
entity.CloseResponse(HttpStatusCode.Forbidden);
@@ -642,7 +644,7 @@ namespace VNLib.Plugins.Essentials
entity.CloseResponse(HttpStatusCode.NotFound);
break;
}
-
+
return FileProcessArgs.VirtualSkip;
}
@@ -654,9 +656,9 @@ namespace VNLib.Plugins.Essentials
/// <returns>The results to return to the file processor, this method must return an argument</returns>
protected virtual async ValueTask<FileProcessArgs> RouteFileAsync(HttpEntity entity)
{
- //Read local copy of the router
-
+ //Read local copy of the router
IPageRouter? router = Router;
+
//Make sure router is set
if (router == null)
{
@@ -668,8 +670,7 @@ namespace VNLib.Plugins.Essentials
PostProcessFile(entity, in routine);
//Return the routine
return routine;
- }
-
+ }
/// <summary>
/// Finds the file specified by the request and the server root the user has requested.
diff --git a/lib/Plugins.Essentials/src/Extensions/ConnectionInfoExtensions.cs b/lib/Plugins.Essentials/src/Extensions/ConnectionInfoExtensions.cs
index a91f196..8cabffd 100644
--- a/lib/Plugins.Essentials/src/Extensions/ConnectionInfoExtensions.cs
+++ b/lib/Plugins.Essentials/src/Extensions/ConnectionInfoExtensions.cs
@@ -24,10 +24,12 @@
using System;
using System.Net;
+using System.Linq;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using VNLib.Net.Http;
+using VNLib.Utils.Extensions;
#nullable enable
@@ -52,6 +54,69 @@ namespace VNLib.Plugins.Essentials.Extensions
/// Cache-Control header value for disabling cache
/// </summary>
public static readonly string NO_CACHE_RESPONSE_HEADER_VALUE = HttpHelpers.GetCacheString(CacheType.NoCache | CacheType.NoStore | CacheType.Revalidate);
+
+
+ /// <summary>
+ /// Determines if the client accepts the response content type
+ /// </summary>
+ /// <param name="server"></param>
+ /// <param name="type">The desired content type</param>
+ /// <returns>True if the client accepts the content type, false otherwise</returns>
+ public static bool Accepts(this IConnectionInfo server, ContentType type)
+ {
+ //Get the content type string from he specified content type
+ string contentType = HttpHelpers.GetContentTypeString(type);
+ return Accepts(server, contentType);
+ }
+
+ /// <summary>
+ /// Determines if the client accepts the response content type
+ /// </summary>
+ /// <param name="server"></param>
+ /// <param name="contentType">The desired content type</param>
+ /// <returns>True if the client accepts the content type, false otherwise</returns>
+ public static bool Accepts(this IConnectionInfo server, string contentType)
+ {
+ if (AcceptsAny(server))
+ {
+ return true;
+ }
+
+ //If client accepts exact requested encoding
+ if (server.Accept.Contains(contentType, StringComparer.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+
+ //Search for the content-sub-type
+
+ //Get prinary side of mime type
+ ReadOnlySpan<char> primary = contentType.AsSpan().SliceBeforeParam('/');
+
+ foreach(string accept in server.Accept)
+ {
+ //The the accept subtype
+ ReadOnlySpan<char> ctSubType = accept.AsSpan().SliceBeforeParam('/');
+
+ //See if accepts any subtype, or the primary sub-type matches
+ if (ctSubType[0] == '*' || ctSubType.Equals(primary, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Determines if the connection accepts any content type
+ /// </summary>
+ /// <returns>true if the connection accepts any content typ, false otherwise</returns>
+ private static bool AcceptsAny(this IConnectionInfo server)
+ {
+ //Accept any if no accept header was present, or accept all value */*
+ return server.Accept.Count == 0 || server.Accept.Where(static t => t.StartsWith("*/*", StringComparison.OrdinalIgnoreCase)).Any();
+ }
/// <summary>
/// Gets the <see cref="HttpRequestHeader.IfModifiedSince"/> header value and converts its value to a datetime value
diff --git a/lib/Plugins.Essentials/src/Oauth/IOAuth2Provider.cs b/lib/Plugins.Essentials/src/Oauth/IOAuth2Provider.cs
deleted file mode 100644
index 30944b8..0000000
--- a/lib/Plugins.Essentials/src/Oauth/IOAuth2Provider.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials
-* File: IOAuth2Provider.cs
-*
-* IOAuth2Provider.cs is part of VNLib.Plugins.Essentials which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* VNLib.Plugins.Essentials is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
-*/
-
-using System;
-using System.Threading.Tasks;
-
-using VNLib.Plugins.Essentials.Sessions;
-
-namespace VNLib.Plugins.Essentials.Oauth
-{
- /// <summary>
- /// An interface that Oauth2 serice providers must implement
- /// to provide sessions to an <see cref="EventProcessor"/>
- /// processor endpoint processor
- /// </summary>
- public interface IOAuth2Provider : ISessionProvider
- {
- /// <summary>
- /// Gets a value indicating how long a session may be valid for
- /// </summary>
- public TimeSpan MaxTokenLifetime { get; }
- }
-} \ No newline at end of file
diff --git a/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs b/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs
index 11ab61a..3bce1f6 100644
--- a/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs
+++ b/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs
@@ -134,15 +134,15 @@ namespace VNLib.Plugins.Essentials.Oauth
//Set the error result in the header
ev.Server.Headers[HttpResponseHeader.WwwAuthenticate] = error switch
{
- ErrorType.InvalidRequest => $"Bearer error=\"invalid_request\"",
- ErrorType.UnauthorizedClient => $"Bearer error=\"unauthorized_client\"",
- 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.InvalidClient => $"Bearer error=\"invalid_client\"",
- ErrorType.InvalidToken => $"Bearer error=\"invalid_token\"",
- _ => $"Bearer error=\"error\"",
+ ErrorType.InvalidRequest => "Bearer error=\"invalid_request\"",
+ ErrorType.UnauthorizedClient => "Bearer error=\"unauthorized_client\"",
+ 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.InvalidClient => "Bearer error=\"invalid_client\"",
+ ErrorType.InvalidToken => "Bearer error=\"invalid_token\"",
+ _ => "Bearer error=\"error\"",
};
//Close the response with the status code
ev.CloseResponse(code);
diff --git a/lib/Plugins.Essentials/src/Oauth/OauthSessionCacheExhaustedException.cs b/lib/Plugins.Essentials/src/Oauth/OauthSessionCacheExhaustedException.cs
deleted file mode 100644
index da91444..0000000
--- a/lib/Plugins.Essentials/src/Oauth/OauthSessionCacheExhaustedException.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials
-* File: OauthSessionCacheExhaustedException.cs
-*
-* OauthSessionCacheExhaustedException.cs is part of VNLib.Plugins.Essentials which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* VNLib.Plugins.Essentials is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see https://www.gnu.org/licenses/.
-*/
-
-using System;
-
-
-namespace VNLib.Plugins.Essentials.Oauth
-{
- /// <summary>
- /// Raised when the session cache space has been exhausted and cannot
- /// load the new session into cache.
- /// </summary>
- public class OauthSessionCacheExhaustedException : Exception
- {
- public OauthSessionCacheExhaustedException(string message) : base(message)
- {}
- public OauthSessionCacheExhaustedException(string message, Exception innerException) : base(message, innerException)
- {}
- public OauthSessionCacheExhaustedException()
- {}
- }
-} \ No newline at end of file
diff --git a/lib/Plugins.Essentials/src/Sessions/SessionBase.cs b/lib/Plugins.Essentials/src/Sessions/SessionBase.cs
index 46e6ec8..100818b 100644
--- a/lib/Plugins.Essentials/src/Sessions/SessionBase.cs
+++ b/lib/Plugins.Essentials/src/Sessions/SessionBase.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -31,7 +31,7 @@ using VNLib.Utils;
namespace VNLib.Plugins.Essentials.Sessions
{
/// <summary>
- /// Provides a base class for the <see cref="ISession"/> interface for exclusive use within a multithreaded
+ /// Provides a base class for the <see cref="ISession"/> interface that handles basic housekeeping
/// context
/// </summary>
public abstract class SessionBase : ISession