made generic, still broken
This commit is contained in:
parent
c0511cebe0
commit
a9eb927570
1 changed files with 358 additions and 345 deletions
123
src/main.zig
123
src/main.zig
|
@ -10,7 +10,7 @@ pub fn main() !void {
|
|||
const allocator = gpa.allocator();
|
||||
|
||||
const address = try net.Address.parseIp("0.0.0.0", 8080);
|
||||
var listener = Listener.init(.{
|
||||
var listener = App.init(.{
|
||||
.address = address,
|
||||
.allocator = allocator,
|
||||
.root_handler = &handleError,
|
||||
|
@ -18,22 +18,26 @@ pub fn main() !void {
|
|||
defer listener.deinit();
|
||||
|
||||
try listener.router.putRoute("/", &handle);
|
||||
try listener.router.putRoute("/error", &handleError);
|
||||
try listener.router.putRoute("//pee", &handleError);
|
||||
try listener.router.putRoute("/error/*", &handleError);
|
||||
// try listener.router.putRoute("/error", &handleError);
|
||||
// try listener.router.putRoute("//pee", &handleError);
|
||||
// try listener.router.putRoute("/error/*", &handleError);
|
||||
|
||||
try listener.listen();
|
||||
}
|
||||
|
||||
pub fn handle(event: *Listener.Event) anyerror!void {
|
||||
pub const App = Listener(DummyContext);
|
||||
pub const DummyContext = struct {};
|
||||
|
||||
pub fn handle(event: *App.Event) anyerror!void {
|
||||
try event.res.body.appendSlice("hello there");
|
||||
}
|
||||
|
||||
pub fn handleError(event: *Listener.Event) anyerror!void {
|
||||
pub fn handleError(event: *App.Event) anyerror!void {
|
||||
try event.res.body.appendSlice("ahoy, an error occurred");
|
||||
}
|
||||
|
||||
pub const Listener = struct {
|
||||
pub fn Listener(comptime Context: type) type {
|
||||
return struct {
|
||||
allocator: mem.Allocator,
|
||||
|
||||
/// Listen address
|
||||
|
@ -48,7 +52,9 @@ pub const Listener = struct {
|
|||
root_handler: HandlerFn,
|
||||
};
|
||||
|
||||
pub fn init(options: Options) Listener {
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(options: Options) Self {
|
||||
return .{
|
||||
.address = options.address,
|
||||
.allocator = options.allocator,
|
||||
|
@ -56,12 +62,12 @@ pub const Listener = struct {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Listener) void {
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.router.deinit();
|
||||
}
|
||||
|
||||
/// Listens for new connections forever
|
||||
pub fn listen(self: *Listener) !void {
|
||||
pub fn listen(self: *Self) !void {
|
||||
var arena = heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
|
@ -78,11 +84,13 @@ pub const Listener = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle(self: *Listener, server: *http.Server, allocator: mem.Allocator) !void {
|
||||
fn handle(self: *Self, server: *http.Server, allocator: mem.Allocator) !void {
|
||||
handler: while (true) {
|
||||
var req = server.receiveHead() catch |e| if (e == error.HttpConnectionClosing) break :handler else return e;
|
||||
|
||||
var ctx = Context{};
|
||||
var event = Event{
|
||||
.ctx = &ctx,
|
||||
.req = .{
|
||||
.uri = try std.Uri.parseWithoutScheme(req.head.target),
|
||||
.headers = std.ArrayList(*const http.Header).init(allocator),
|
||||
|
@ -97,7 +105,8 @@ pub const Listener = struct {
|
|||
var header_it = req.iterateHeaders();
|
||||
while (header_it.next()) |header| try event.req.headers.append(&header);
|
||||
|
||||
try self.router.handle(&event);
|
||||
const route = try self.router.getRoute(event.req.uri.path);
|
||||
try route.handler(&event);
|
||||
|
||||
try respondFromEvent(&event, &req, allocator);
|
||||
}
|
||||
|
@ -117,6 +126,7 @@ pub const Listener = struct {
|
|||
|
||||
/// Single request-response context
|
||||
pub const Event = struct {
|
||||
ctx: *Context,
|
||||
req: Request,
|
||||
res: Response,
|
||||
|
||||
|
@ -157,15 +167,15 @@ pub const Listener = struct {
|
|||
}
|
||||
|
||||
pub fn deinit(self: *Router) void {
|
||||
self.root_node.deinit(self.arena.allocator());
|
||||
self.root_node.deinit(self.arena.allocator(), null);
|
||||
self.arena.deinit();
|
||||
// self.static_routes.deinit();
|
||||
}
|
||||
|
||||
pub fn handle(self: *Router, event: *Listener.Event) !void {
|
||||
const route = try self.getRoute(event.req.uri.path);
|
||||
try route.handler(event);
|
||||
}
|
||||
// pub fn handle(self: *Router, event: *Listener.Event) !void {
|
||||
// const route = try self.getRoute(event.req.uri.path);
|
||||
// try route.handler(event);
|
||||
// }
|
||||
|
||||
/// Insert a route if the path is not already present, otherwise overwrite preexisting HandlerFn.
|
||||
pub fn putRoute(self: *Router, path: []const u8, handler: HandlerFn) !void {
|
||||
|
@ -357,51 +367,54 @@ pub const Listener = struct {
|
|||
|
||||
pub fn deinit(self: *Node, allocator: mem.Allocator, section: ?[]const u8) void {
|
||||
std.debug.print("deiniting node with {d} children.. and {d} placeholder_children\n", .{ self.children.count(), self.placeholder_children.items.len });
|
||||
if (section) |sec| if (self.parent) |parent| parent.children.remove(sec);
|
||||
if (section) |sec| if (self.parent) |parent| {
|
||||
_ = parent.children.remove(sec);
|
||||
};
|
||||
for (self.placeholder_children.items) |child| std.debug.print("child {any}\n", .{child}); // child.deinit(allocator);
|
||||
self.placeholder_children.deinit();
|
||||
var child_it = self.children.valueIterator();
|
||||
while (child_it.next()) |child| child.*.deinit(allocator);
|
||||
while (child_it.next()) |child| child.*.deinit(allocator, section);
|
||||
self.children.deinit();
|
||||
allocator.destroy(self);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test "Router" {
|
||||
var router = Listener.Router.init(std.testing.allocator, &dummyHandler);
|
||||
defer router.deinit();
|
||||
|
||||
try router.putRoute("/foo", &hummyDandler);
|
||||
try router.putRoute("/foo/bar", &hummyDandler);
|
||||
try router.putRoute("/foo/foobar", &tummyCandler);
|
||||
try router.putRoute("/bar", &hummyDandler);
|
||||
|
||||
try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/")).handler);
|
||||
try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/foo")).handler);
|
||||
try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/foo/bar")).handler);
|
||||
try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/foobar")).handler);
|
||||
try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/bar")).handler);
|
||||
|
||||
try std.testing.expect(router.removeRoute("/foo"));
|
||||
|
||||
try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/foo/bar")).handler);
|
||||
try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/foo")).handler);
|
||||
try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/")).handler);
|
||||
|
||||
try router.putRoute("/foo", &hummyDandler);
|
||||
try router.putRoute("/foo/**", &tummyCandler);
|
||||
try router.putRoute("/bar/*", &tummyCandler);
|
||||
|
||||
try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/foo")).handler);
|
||||
try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/bar")).handler);
|
||||
try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/bar/foo")).handler);
|
||||
try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/foof")).handler);
|
||||
|
||||
try std.testing.expect(router.removeRoute("/bar/*"));
|
||||
};
|
||||
}
|
||||
|
||||
fn dummyHandler(_: *Listener.Event) anyerror!void {}
|
||||
fn hummyDandler(_: *Listener.Event) anyerror!void {}
|
||||
fn tummyCandler(_: *Listener.Event) anyerror!void {}
|
||||
// test "Router" {
|
||||
// var router = Listener.Router.init(std.testing.allocator, &dummyHandler);
|
||||
// defer router.deinit();
|
||||
|
||||
// try router.putRoute("/foo", &hummyDandler);
|
||||
// try router.putRoute("/foo/bar", &hummyDandler);
|
||||
// try router.putRoute("/foo/foobar", &tummyCandler);
|
||||
// try router.putRoute("/bar", &hummyDandler);
|
||||
|
||||
// try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/")).handler);
|
||||
// try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/foo")).handler);
|
||||
// try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/foo/bar")).handler);
|
||||
// try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/foobar")).handler);
|
||||
// try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/bar")).handler);
|
||||
|
||||
// try std.testing.expect(router.removeRoute("/foo"));
|
||||
|
||||
// try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/foo/bar")).handler);
|
||||
// try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/foo")).handler);
|
||||
// try std.testing.expectEqual(&dummyHandler, (try router.getRoute("/")).handler);
|
||||
|
||||
// try router.putRoute("/foo", &hummyDandler);
|
||||
// try router.putRoute("/foo/**", &tummyCandler);
|
||||
// try router.putRoute("/bar/*", &tummyCandler);
|
||||
|
||||
// try std.testing.expectEqual(&hummyDandler, (try router.getRoute("/foo")).handler);
|
||||
// try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/bar")).handler);
|
||||
// try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/bar/foo")).handler);
|
||||
// try std.testing.expectEqual(&tummyCandler, (try router.getRoute("/foo/foof")).handler);
|
||||
|
||||
// try std.testing.expect(router.removeRoute("/bar/*"));
|
||||
// }
|
||||
|
||||
// fn dummyHandler(_: *Listener.Event) anyerror!void {}
|
||||
// fn hummyDandler(_: *Listener.Event) anyerror!void {}
|
||||
// fn tummyCandler(_: *Listener.Event) anyerror!void {}
|
||||
|
|
Loading…
Add table
Reference in a new issue