made generic, still broken

This commit is contained in:
Jeeves 2024-03-26 16:22:48 -06:00
parent c0511cebe0
commit a9eb927570

View file

@ -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 {}