add wildcard fallback handlers

This commit is contained in:
GHXX 2026-06-21 07:24:47 +02:00
parent fb91d099ac
commit be9dd343bc

View File

@ -89,6 +89,7 @@ public sealed class HttpServer {
private readonly Dictionary<string, PathTree<EndpointInvocationInfo>> pathEndpointMethodInfosTrees = new(); // reqmethod : pathtree private readonly Dictionary<string, PathTree<EndpointInvocationInfo>> pathEndpointMethodInfosTrees = new(); // reqmethod : pathtree
private static readonly Type[] expectedEndpointParameterTypes = new[] { typeof(RequestContext) }; private static readonly Type[] expectedEndpointParameterTypes = new[] { typeof(RequestContext) };
internal static readonly int expectedEndpointParameterPrefixCount = expectedEndpointParameterTypes.Length; internal static readonly int expectedEndpointParameterPrefixCount = expectedEndpointParameterTypes.Length;
private readonly Dictionary<string, Func<RequestContext, Task<bool>>> wildcardFallbackHandlers = new(); // reqmethod : handler
public void RegisterEndpointsFromType<T>(Func<T>? instanceFactory = null) where T : class { // T cannot be static, as generic args must be nonstatic public void RegisterEndpointsFromType<T>(Func<T>? instanceFactory = null) where T : class { // T cannot be static, as generic args must be nonstatic
if (stringToTypeParameterConverters.Count == 0) if (stringToTypeParameterConverters.Count == 0)
@ -267,8 +268,9 @@ public sealed class HttpServer {
/* Finding the endpoint that should process the request: /* Finding the endpoint that should process the request:
* 1. Try to see if there is a simple endpoint where request method and path match * 1. Try to see if there is a simple endpoint where request method and path match
* 2. Otherwise, try to see if a path-parameter-endpoint matches (duplicates throw an error on startup) * 2. Otherwise, try to see if a path-parameter-endpoint matches (duplicates throw an error on startup)
* 3. Otherwise, check if it is inside a static serve path * 3. Otherwise, check if wildcardFallbackHandlers contains a handler for the current requestMethod. If this method returns false 'request was not handled', continue, otherwise skip all future steps.
* 4. Otherwise, show 404 page */ * 4. Otherwise, check if it is inside a static serve path
* 5. Otherwise, show 404 page */
EndpointInvocationInfo? pathEndpointInvocationInfo = null; EndpointInvocationInfo? pathEndpointInvocationInfo = null;
if (simpleEndpointMethodInfos.TryGetValue(requestMethod, reqPath, out var simpleEndpointInvocationInfo) || if (simpleEndpointMethodInfos.TryGetValue(requestMethod, reqPath, out var simpleEndpointInvocationInfo) ||
@ -354,7 +356,17 @@ public sealed class HttpServer {
// todo read and convert pathparams // todo read and convert pathparams
await (Task) (mi.Invoke(endpointInvocationInfo.typeInstanceReference, convertedMParamValues) ?? throw new NullReferenceException("Website func returned null unexpectedly")); await (Task) (mi.Invoke(endpointInvocationInfo.typeInstanceReference, convertedMParamValues) ?? throw new NullReferenceException("Website func returned null unexpectedly"));
} else { // try to find suitable static serve path } else {
// ---------------- check for fallback wildcard handler ----------------
if (wildcardFallbackHandlers.TryGetValue(requestMethod, out var handler)) {
var handledByWildcard = await handler.Invoke(rc);
if (handledByWildcard) { // if that handler was able to handle the request, end execution
return;
}
}
// ---------------------------------------------------------------------
// try to find suitable static serve path
if (requestMethod == "GET") if (requestMethod == "GET")
foreach (var (k, v) in staticServePaths) { foreach (var (k, v) in staticServePaths) {
if (reqPath.StartsWith(k)) { // do a static serve if (reqPath.StartsWith(k)) { // do a static serve
@ -415,4 +427,14 @@ public sealed class HttpServer {
} }
} catch (ObjectDisposedException) { } } catch (ObjectDisposedException) { }
} }
/// <summary>
/// Adds a wildcard fallback handler that receives any request that was not matched by a more explicit endpoint.
/// The handler is supposed to return 'true' if the request was handled correctly and thus execution shall end. Return 'false' to try to serve the file from a static-serve path.
/// </summary>
/// <param name="reqMethod"></param>
/// <param name="requestHandler">This method must return whether the reuqest was handled; returning false makes handling act as if this handler never ran</param>
public void RegisterWildcardFallbackHandler(HttpRequestType reqMethod, Func<RequestContext, Task<bool>> requestHandler) {
wildcardFallbackHandlers.Add(Enum.GetName(reqMethod) ?? throw new NotImplementedException(), requestHandler);
}
} }