Add Route.bind
This commit is contained in:
parent
626a7d33b0
commit
283b85cfcc
4 changed files with 226 additions and 152 deletions
|
@ -3,7 +3,7 @@ const root = @import("root");
|
|||
|
||||
pub const Router = @import("./http/Router.zig");
|
||||
|
||||
const ciutf8 = root.ciutf8;
|
||||
const ciutf8 = @import("./util.zig").ciutf8;
|
||||
const Reader = std.net.Stream.Reader;
|
||||
const Writer = std.net.Stream.Writer;
|
||||
const Route = Router.Route;
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
const std = @import("std");
|
||||
const root = @import("root");
|
||||
|
||||
const Context = root.http.Context;
|
||||
const Method = root.http.Method;
|
||||
const ciutf8 = root.ciutf8;
|
||||
const util = @import("../util.zig");
|
||||
const http = @import("../http.zig");
|
||||
|
||||
const Method = http.Method;
|
||||
const ciutf8 = util.ciutf8;
|
||||
|
||||
pub fn Router(comptime Context: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
routes: []const Route,
|
||||
|
||||
pub const Route = struct {
|
||||
|
@ -19,7 +21,7 @@ pub const Route = struct {
|
|||
fn normalize(comptime path: []const u8) []const u8 {
|
||||
var arr: [path.len]u8 = undefined;
|
||||
|
||||
var i = 0;
|
||||
comptime var i = 0;
|
||||
for (path) |ch| {
|
||||
if (i == 0 and ch == '/') continue;
|
||||
if (i > 0 and ch == '/' and arr[i - 1] == '/') continue;
|
||||
|
@ -158,7 +160,7 @@ pub fn routeRequest(self: Self, ctx: *Context) !void {
|
|||
for (self.routes) |*route| {
|
||||
if (route.method == ctx.request.method and route.matches(ctx.request.path)) {
|
||||
std.log.info("{s} {s}", .{ @tagName(ctx.request.method), ctx.request.path });
|
||||
ctx.request.route = route;
|
||||
//ctx.request.route = route;
|
||||
|
||||
var buf = try ctx.allocator.allocWithOptions(u8, @frameSize(route.handler), 8, null);
|
||||
defer ctx.allocator.free(buf);
|
||||
|
@ -169,3 +171,60 @@ pub fn routeRequest(self: Self, ctx: *Context) !void {
|
|||
std.log.info("404 {s} {s}", .{ @tagName(ctx.request.method), ctx.request.path });
|
||||
try handleNotFound(ctx);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const TestContext = struct {
|
||||
request: struct {
|
||||
method: Method,
|
||||
path: []const u8,
|
||||
},
|
||||
allocator: std.mem.Allocator = std.testing.allocator,
|
||||
};
|
||||
const TestRouter = Router(TestContext);
|
||||
const TestRoute = TestRouter.Route;
|
||||
|
||||
fn CallTracker(comptime _uniq: anytype, comptime next: TestRoute.Handler) type {
|
||||
_ = _uniq;
|
||||
return struct {
|
||||
var calls: u32 = 0;
|
||||
fn func(ctx: *TestContext, route: *const TestRoute) !void {
|
||||
calls += 1;
|
||||
return next(ctx, route);
|
||||
}
|
||||
|
||||
fn expectCalled(times: u32) !void {
|
||||
return std.testing.expectEqual(times, calls);
|
||||
}
|
||||
|
||||
fn reset() void {
|
||||
calls = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn expectNotCalled(_: *TestContext, _: *const TestRoute) !void {
|
||||
return error.TestWrongRouteChosen;
|
||||
}
|
||||
|
||||
fn dummyHandler(_: *TestContext, _: *const TestRoute) !void {}
|
||||
|
||||
test "routeRequest" {
|
||||
const call_tracker = CallTracker(.{}, dummyHandler);
|
||||
const test_routes = [_]TestRoute{
|
||||
TestRoute.from(.GET, "/ab", expectNotCalled),
|
||||
TestRoute.from(.GET, "/abc", call_tracker.func),
|
||||
TestRoute.from(.GET, "/abcdefg", expectNotCalled),
|
||||
TestRoute.from(.GET, "/", expectNotCalled),
|
||||
};
|
||||
var context = TestContext{
|
||||
.request = .{
|
||||
.method = .GET,
|
||||
.path = "/abc",
|
||||
},
|
||||
};
|
||||
|
||||
try (TestRouter{ .routes = &test_routes }).routeRequest(&context);
|
||||
|
||||
try call_tracker.expectCalled(1);
|
||||
}
|
||||
|
|
|
@ -87,3 +87,7 @@ pub fn main() anyerror!void {
|
|||
_ = async http.handleConnection(conn);
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
_ = http;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,17 @@ test {
|
|||
_ = _tests;
|
||||
}
|
||||
const _tests = struct {
|
||||
test "RouteWithContext(T).bind" {
|
||||
const R = RouteWithContext(Context);
|
||||
const r = R.bind(.GET, "//ab//cd", dummyHandler);
|
||||
|
||||
try std.testing.expectEqual(R{
|
||||
.method = .GET,
|
||||
.path = "/ab/cd",
|
||||
.handler = dummyHandler,
|
||||
}, r);
|
||||
}
|
||||
|
||||
fn CallTracker(comptime _uniq: anytype, comptime next: fn (Context) void) type {
|
||||
_ = _uniq;
|
||||
return struct {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue