diff --git a/SimpleHttpServer/HttpServer.cs b/SimpleHttpServer/HttpServer.cs index 9a27602..5e0dccd 100644 --- a/SimpleHttpServer/HttpServer.cs +++ b/SimpleHttpServer/HttpServer.cs @@ -89,6 +89,7 @@ public sealed class HttpServer { private readonly Dictionary> pathEndpointMethodInfosTrees = new(); // reqmethod : pathtree private static readonly Type[] expectedEndpointParameterTypes = new[] { typeof(RequestContext) }; internal static readonly int expectedEndpointParameterPrefixCount = expectedEndpointParameterTypes.Length; + private readonly Dictionary>> wildcardFallbackHandlers = new(); // reqmethod : handler public void RegisterEndpointsFromType(Func? instanceFactory = null) where T : class { // T cannot be static, as generic args must be nonstatic if (stringToTypeParameterConverters.Count == 0) @@ -267,8 +268,9 @@ public sealed class HttpServer { /* Finding the endpoint that should process the request: * 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) - * 3. Otherwise, check if it is inside a static serve path - * 4. Otherwise, show 404 page */ + * 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, check if it is inside a static serve path + * 5. Otherwise, show 404 page */ EndpointInvocationInfo? pathEndpointInvocationInfo = null; if (simpleEndpointMethodInfos.TryGetValue(requestMethod, reqPath, out var simpleEndpointInvocationInfo) || @@ -354,7 +356,17 @@ public sealed class HttpServer { // todo read and convert pathparams 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") foreach (var (k, v) in staticServePaths) { if (reqPath.StartsWith(k)) { // do a static serve @@ -415,4 +427,14 @@ public sealed class HttpServer { } } catch (ObjectDisposedException) { } } + + /// + /// 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. + /// + /// + /// This method must return whether the reuqest was handled; returning false makes handling act as if this handler never ran + public void RegisterWildcardFallbackHandler(HttpRequestType reqMethod, Func> requestHandler) { + wildcardFallbackHandlers.Add(Enum.GetName(reqMethod) ?? throw new NotImplementedException(), requestHandler); + } } \ No newline at end of file