Fixed mapping to method bits.
Build and Test Module / build-and-test (push) Successful in 11s Details

This commit is contained in:
Andrew Lalis 2025-07-27 12:02:48 -04:00
parent 27ccf2ce3d
commit 4fcd24f2b4
1 changed files with 20 additions and 16 deletions

View File

@ -26,17 +26,18 @@ private struct HandlerMapping {
} }
/// Maps each HTTP method to a bit value, so we can use bit-masking for handler mappings. /// Maps each HTTP method to a bit value, so we can use bit-masking for handler mappings.
immutable ushort[HttpMethod] HTTP_METHOD_BITS = [ ushort getMethodBit(in string method) {
HttpMethod.GET: 1 >> 0, if (method == HttpMethod.GET) return 1;
HttpMethod.HEAD: 1 >> 1, if (method == HttpMethod.HEAD) return 2;
HttpMethod.POST: 1 >> 2, if (method == HttpMethod.POST) return 4;
HttpMethod.PUT: 1 >> 3, if (method == HttpMethod.PUT) return 8;
HttpMethod.DELETE: 1 >> 4, if (method == HttpMethod.DELETE) return 16;
HttpMethod.CONNECT: 1 >> 5, if (method == HttpMethod.CONNECT) return 32;
HttpMethod.OPTIONS: 1 >> 6, if (method == HttpMethod.OPTIONS) return 64;
HttpMethod.TRACE: 1 >> 7, if (method == HttpMethod.TRACE) return 128;
HttpMethod.PATCH: 1 >> 8 if (method == HttpMethod.PATCH) return 256;
]; throw new Exception("Unknown HTTP method: " ~ method);
}
/** /**
* Computes a bitmask from a list of HTTP methods. * Computes a bitmask from a list of HTTP methods.
@ -47,7 +48,7 @@ immutable ushort[HttpMethod] HTTP_METHOD_BITS = [
ushort methodMaskFromMethods(HttpMethod[] methods) { ushort methodMaskFromMethods(HttpMethod[] methods) {
ushort mask = 0; ushort mask = 0;
foreach (method; methods) { foreach (method; methods) {
mask |= HTTP_METHOD_BITS[method]; mask |= getMethodBit(method);
} }
return mask; return mask;
} }
@ -149,7 +150,7 @@ class PathHandler : HttpRequestHandler {
* Returns: This path handler, for method chaining. * Returns: This path handler, for method chaining.
*/ */
PathHandler addMapping(HttpMethod method, string pattern, HttpRequestHandler handler) { PathHandler addMapping(HttpMethod method, string pattern, HttpRequestHandler handler) {
this.mappings ~= HandlerMapping(handler, HTTP_METHOD_BITS[method], [pattern]); this.mappings ~= HandlerMapping(handler, getMethodBit(method), [pattern]);
return this; return this;
} }
/// ///
@ -159,7 +160,7 @@ class PathHandler : HttpRequestHandler {
} }
/// ///
PathHandler addMapping(HttpMethod method, string[] patterns, HttpRequestHandler handler) { PathHandler addMapping(HttpMethod method, string[] patterns, HttpRequestHandler handler) {
this.mappings ~= HandlerMapping(handler, HTTP_METHOD_BITS[method], patterns.idup); this.mappings ~= HandlerMapping(handler, getMethodBit(method), patterns.idup);
return this; return this;
} }
/// ///
@ -211,7 +212,7 @@ class PathHandler : HttpRequestHandler {
* Returns: The handler that matches the request, or null if none is found. * Returns: The handler that matches the request, or null if none is found.
*/ */
private HttpRequestHandler findMappedHandler(ref ServerHttpRequest request) { private HttpRequestHandler findMappedHandler(ref ServerHttpRequest request) {
ushort methodBit = HTTP_METHOD_BITS[request.method]; const ushort methodBit = getMethodBit(request.method);
foreach (HandlerMapping mapping; mappings) { foreach (HandlerMapping mapping; mappings) {
if ((mapping.methodsMask & methodBit) > 0) { if ((mapping.methodsMask & methodBit) > 0) {
foreach (string pattern; mapping.patterns) { foreach (string pattern; mapping.patterns) {
@ -257,7 +258,8 @@ unittest {
.addMapping(HttpMethod.GET, "/home", new SimpleOkHandler()) .addMapping(HttpMethod.GET, "/home", new SimpleOkHandler())
.addMapping(HttpMethod.GET, "/users", new SimpleOkHandler()) .addMapping(HttpMethod.GET, "/users", new SimpleOkHandler())
.addMapping(HttpMethod.GET, "/users/:id:ulong", new SimpleOkHandler()) .addMapping(HttpMethod.GET, "/users/:id:ulong", new SimpleOkHandler())
.addMapping(HttpMethod.GET, "/api/*", new SimpleOkHandler()); .addMapping(HttpMethod.GET, "/api/*", new SimpleOkHandler())
.addMapping(HttpMethod.POST, "/api/do-something", new SimpleOkHandler());
struct RequestAndResponse { struct RequestAndResponse {
ServerHttpRequest request; ServerHttpRequest request;
@ -291,4 +293,6 @@ unittest {
assert(result7.response.status == HttpStatus.NOT_FOUND); assert(result7.response.status == HttpStatus.NOT_FOUND);
auto result8 = generateHandledData(HttpMethod.GET, "/"); auto result8 = generateHandledData(HttpMethod.GET, "/");
assert(result8.response.status == HttpStatus.NOT_FOUND); assert(result8.response.status == HttpStatus.NOT_FOUND);
auto result9 = generateHandledData(HttpMethod.POST, "/api/do-something");
assert(result9.response.status == HttpStatus.OK);
} }