Turn routers into functions

This commit is contained in:
jaina heartles 2022-05-22 13:07:30 -07:00
parent b2430b333c
commit f2aec8249b

View file

@ -168,11 +168,13 @@ fn makeRoute(
}.func; }.func;
} }
pub fn Router(comptime Context: type, comptime routes: []const Route(Context)) type { fn RouterFn(comptime Context: type) type {
return struct { return fn (http.Method, path: []const u8, Context) HttpError!void;
const Self = @This(); }
pub fn dispatch(_: *const Self, method: http.Method, path: []const u8, ctx: Context) HttpError!void { pub fn makeRouter(comptime Context: type, comptime routes: []const Route(Context)) RouterFn(Context) {
return struct {
fn dispatch(method: http.Method, path: []const u8, ctx: Context) HttpError!void {
for (routes) |r| { for (routes) |r| {
return r(ctx, method, path) catch |err| switch (err) { return r(ctx, method, path) catch |err| switch (err) {
error.Http404 => continue, error.Http404 => continue,
@ -182,7 +184,7 @@ pub fn Router(comptime Context: type, comptime routes: []const Route(Context)) t
return error.Http404; return error.Http404;
} }
}; }.dispatch;
} }
test { test {
@ -312,18 +314,18 @@ const _tests = struct {
makeRoute(.GET, "/b", mock_b.func), makeRoute(.GET, "/b", mock_b.func),
}; };
const router = Router(TestContext, &routes){}; const router = makeRouter(TestContext, &routes);
_ = try router.dispatch(.GET, "/a", 10); _ = try router(.GET, "/a", 10);
try mock_a.expectCalledOnceWith(10, .{}); try mock_a.expectCalledOnceWith(10, .{});
try mock_b.expectNotCalled(); try mock_b.expectNotCalled();
mock_a.reset(); mock_a.reset();
_ = try router.dispatch(.GET, "/b", 0); _ = try router(.GET, "/b", 0);
try mock_a.expectNotCalled(); try mock_a.expectNotCalled();
try mock_b.expectCalledOnceWith(0, .{}); try mock_b.expectCalledOnceWith(0, .{});
mock_b.reset(); mock_b.reset();
try std.testing.expectError(error.Http404, router.dispatch(.GET, "/c", 0)); try std.testing.expectError(error.Http404, router(.GET, "/c", 0));
} }
test "Router(T).dispatch same path different methods" { test "Router(T).dispatch same path different methods" {
@ -335,13 +337,13 @@ const _tests = struct {
makeRoute(.POST, "/a", mock_post.func), makeRoute(.POST, "/a", mock_post.func),
}; };
const router = Router(TestContext, &routes){}; const router = makeRouter(TestContext, &routes);
_ = try router.dispatch(.GET, "/a", 10); _ = try router(.GET, "/a", 10);
try mock_get.expectCalledOnceWith(10, .{}); try mock_get.expectCalledOnceWith(10, .{});
try mock_post.expectNotCalled(); try mock_post.expectNotCalled();
mock_get.reset(); mock_get.reset();
_ = try router.dispatch(.POST, "/a", 10); _ = try router(.POST, "/a", 10);
try mock_get.expectNotCalled(); try mock_get.expectNotCalled();
try mock_post.expectCalledOnceWith(10, .{}); try mock_post.expectCalledOnceWith(10, .{});
} }
@ -355,13 +357,13 @@ const _tests = struct {
makeRoute(.GET, "/a/b", mock_b.func), makeRoute(.GET, "/a/b", mock_b.func),
}; };
const router = Router(TestContext, &routes){}; const router = makeRouter(TestContext, &routes);
_ = try router.dispatch(.GET, "/a", 10); _ = try router(.GET, "/a", 10);
try mock_a.expectCalledOnceWith(10, .{}); try mock_a.expectCalledOnceWith(10, .{});
try mock_b.expectNotCalled(); try mock_b.expectNotCalled();
mock_a.reset(); mock_a.reset();
_ = try router.dispatch(.GET, "/a/b", 11); _ = try router(.GET, "/a/b", 11);
try mock_a.expectNotCalled(); try mock_a.expectNotCalled();
try mock_b.expectCalledOnceWith(11, .{}); try mock_b.expectCalledOnceWith(11, .{});
} }
@ -373,12 +375,12 @@ const _tests = struct {
makeRoute(.GET, "/test/a", mock_a.func), makeRoute(.GET, "/test/a", mock_a.func),
}; };
const router = Router(TestContext, &routes){}; const router = makeRouter(TestContext, &routes);
_ = try router.dispatch(.GET, "/TEST/A", 10); _ = try router(.GET, "/TEST/A", 10);
try mock_a.expectCalledOnceWith(10, .{}); try mock_a.expectCalledOnceWith(10, .{});
mock_a.reset(); mock_a.reset();
_ = try router.dispatch(.GET, "/TesT/a", 11); _ = try router(.GET, "/TesT/a", 11);
try mock_a.expectCalledOnceWith(11, .{}); try mock_a.expectCalledOnceWith(11, .{});
} }
@ -389,16 +391,16 @@ const _tests = struct {
makeRoute(.GET, "/test/a", mock_a.func), makeRoute(.GET, "/test/a", mock_a.func),
}; };
const router = Router(TestContext, &routes){}; const router = makeRouter(TestContext, &routes);
_ = try router.dispatch(.GET, "/test//a", 10); _ = try router(.GET, "/test//a", 10);
try mock_a.expectCalledOnceWith(10, .{}); try mock_a.expectCalledOnceWith(10, .{});
mock_a.reset(); mock_a.reset();
_ = try router.dispatch(.GET, "//test///////////a////", 11); _ = try router(.GET, "//test///////////a////", 11);
try mock_a.expectCalledOnceWith(11, .{}); try mock_a.expectCalledOnceWith(11, .{});
mock_a.reset(); mock_a.reset();
_ = try router.dispatch(.GET, "test/a", 12); _ = try router(.GET, "test/a", 12);
try mock_a.expectCalledOnceWith(12, .{}); try mock_a.expectCalledOnceWith(12, .{});
} }
@ -411,17 +413,17 @@ const _tests = struct {
makeRoute(.GET, "/test/:a_id/abcd/:b_id", mock_b.func), makeRoute(.GET, "/test/:a_id/abcd/:b_id", mock_b.func),
}; };
const router = Router(TestContext, &routes){}; const router = makeRouter(TestContext, &routes);
_ = try router.dispatch(.GET, "/test/xyz/abcd", 10); _ = try router(.GET, "/test/xyz/abcd", 10);
try mock_a.expectCalledOnceWith(10, .{ .id = "xyz" }); try mock_a.expectCalledOnceWith(10, .{ .id = "xyz" });
try mock_b.expectNotCalled(); try mock_b.expectNotCalled();
mock_a.reset(); mock_a.reset();
try std.testing.expectError(error.Http404, router.dispatch(.GET, "/test//abcd", 10)); try std.testing.expectError(error.Http404, router(.GET, "/test//abcd", 10));
try mock_a.expectNotCalled(); try mock_a.expectNotCalled();
try mock_b.expectNotCalled(); try mock_b.expectNotCalled();
_ = try router.dispatch(.GET, "/test/xyz/abcd/zyx", 10); _ = try router(.GET, "/test/xyz/abcd/zyx", 10);
try mock_a.expectNotCalled(); try mock_a.expectNotCalled();
try mock_b.expectCalledOnceWith(10, .{ .a_id = "xyz", .b_id = "zyx" }); try mock_b.expectCalledOnceWith(10, .{ .a_id = "xyz", .b_id = "zyx" });
} }