much much better(ish)
This commit is contained in:
parent
328391a6a3
commit
0c51038b98
1 changed files with 40 additions and 22 deletions
62
src/main.zig
62
src/main.zig
|
@ -21,6 +21,9 @@ pub fn main() !void {
|
||||||
.root_handler = &handle,
|
.root_handler = &handle,
|
||||||
});
|
});
|
||||||
defer listener.deinit();
|
defer listener.deinit();
|
||||||
|
|
||||||
|
try listener.router.addRoute("/error", &handleError);
|
||||||
|
|
||||||
try listener.listen();
|
try listener.listen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +37,7 @@ pub fn handleError(event: *Listener.Event) anyerror!void {
|
||||||
|
|
||||||
pub const Listener = struct {
|
pub const Listener = struct {
|
||||||
address: net.Address,
|
address: net.Address,
|
||||||
arena: heap.ArenaAllocator,
|
allocator: mem.Allocator,
|
||||||
|
|
||||||
router: Router,
|
router: Router,
|
||||||
|
|
||||||
|
@ -47,43 +50,45 @@ pub const Listener = struct {
|
||||||
pub fn init(options: Options) Listener {
|
pub fn init(options: Options) Listener {
|
||||||
return .{
|
return .{
|
||||||
.address = options.address,
|
.address = options.address,
|
||||||
.arena = heap.ArenaAllocator.init(options.allocator),
|
.allocator = options.allocator,
|
||||||
.router = Router.init(options.allocator, options.root_handler),
|
.router = Router.init(options.allocator, options.root_handler),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Listener) void {
|
pub fn deinit(self: *Listener) void {
|
||||||
self.router.deinit();
|
self.router.deinit();
|
||||||
self.arena.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen(self: *Listener) !void {
|
pub fn listen(self: *Listener) !void {
|
||||||
var tcp = try self.address.listen(.{});
|
var arena = heap.ArenaAllocator.init(self.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
|
||||||
|
var tcp = try self.address.listen(.{ .reuse_address = true });
|
||||||
defer tcp.deinit();
|
defer tcp.deinit();
|
||||||
std.debug.print("listening at: {any}\n", .{self.address});
|
std.debug.print("listening at: {any}\n", .{self.address});
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const read_buf = try self.arena.allocator().alloc(u8, 1024 * 32);
|
const read_buf = try arena.allocator().alloc(u8, 1024 * 32);
|
||||||
const connection = try tcp.accept();
|
const connection = try tcp.accept();
|
||||||
var server = http.Server.init(connection, read_buf);
|
var server = http.Server.init(connection, read_buf);
|
||||||
try self.handle(&server);
|
try self.handle(&server, arena.allocator());
|
||||||
_ = self.arena.reset(.retain_capacity);
|
_ = arena.reset(.retain_capacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(self: *Listener, server: *http.Server) !void {
|
fn handle(self: *Listener, server: *http.Server, allocator: mem.Allocator) !void {
|
||||||
handler: while (true) {
|
handler: while (true) {
|
||||||
var req = server.receiveHead() catch |e| if (e == error.HttpConnectionClosing) break :handler else return e;
|
var req = server.receiveHead() catch |e| if (e == error.HttpConnectionClosing) break :handler else return e;
|
||||||
|
|
||||||
var event = Event{
|
var event = Event{
|
||||||
.req = .{
|
.req = .{
|
||||||
.uri = try std.Uri.parseWithoutScheme(req.head.target),
|
.uri = try std.Uri.parseWithoutScheme(req.head.target),
|
||||||
.headers = std.ArrayList(*const http.Header).init(self.arena.allocator()),
|
.headers = std.ArrayList(*const http.Header).init(allocator),
|
||||||
},
|
},
|
||||||
.res = .{
|
.res = .{
|
||||||
.status = .ok,
|
.status = .ok,
|
||||||
.headers = std.StringHashMap(*http.Header).init(self.arena.allocator()),
|
.headers = std.StringHashMap(*http.Header).init(allocator),
|
||||||
.body = std.ArrayList(u8).init(self.arena.allocator()),
|
.body = std.ArrayList(u8).init(allocator),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,13 +97,13 @@ pub const Listener = struct {
|
||||||
|
|
||||||
try self.router.handle(&event);
|
try self.router.handle(&event);
|
||||||
|
|
||||||
try self.respondFromEvent(&event, &req);
|
try respondFromEvent(&event, &req, allocator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn respondFromEvent(self: *Listener, event: *Event, req: *http.Server.Request) !void {
|
fn respondFromEvent(event: *Event, req: *http.Server.Request, allocator: mem.Allocator) !void {
|
||||||
const res_body = try event.res.body.toOwnedSlice();
|
const res_body = try event.res.body.toOwnedSlice();
|
||||||
const res_headers = try self.arena.allocator().alloc(http.Header, event.res.headers.count());
|
const res_headers = try allocator.alloc(http.Header, event.res.headers.count());
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
var header_it = event.res.headers.iterator();
|
var header_it = event.res.headers.iterator();
|
||||||
while (header_it.next()) |header_ptr| : (i += 1) res_headers[i] = header_ptr.value_ptr.*.*;
|
while (header_it.next()) |header_ptr| : (i += 1) res_headers[i] = header_ptr.value_ptr.*.*;
|
||||||
|
@ -137,7 +142,7 @@ pub const Listener = struct {
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.root_node = .{
|
.root_node = .{
|
||||||
.type = .normal,
|
.type = .normal,
|
||||||
.max_depth = 64,
|
.max_depth = 1024,
|
||||||
.children = std.StringHashMap(*Node).init(allocator),
|
.children = std.StringHashMap(*Node).init(allocator),
|
||||||
.handler = root_handler,
|
.handler = root_handler,
|
||||||
.placeholder_children = std.ArrayList(*Node).init(allocator),
|
.placeholder_children = std.ArrayList(*Node).init(allocator),
|
||||||
|
@ -162,15 +167,13 @@ pub const Listener = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addStaticRoute(self: *Router, path: []const u8, handler: HandlerFn) !void {
|
fn addStaticRoute(self: *Router, path: []const u8, handler: HandlerFn) !void {
|
||||||
try self.static_routes.put(path, .{
|
const node = try Node.init(self.allocator);
|
||||||
.type = .normal,
|
node.handler = handler;
|
||||||
.max_depth = 1,
|
try self.static_routes.put(path, node);
|
||||||
.children = std.StringHashMap(*Node).init(self.allocator),
|
|
||||||
.handler = handler,
|
|
||||||
.placeholder_children = std.ArrayList(*Node).init(self.allocator),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn addNode(self: *Router, path: []const u8) !void {}
|
||||||
|
|
||||||
pub fn route(self: *Router, path: []const u8) HandlerFn {
|
pub fn route(self: *Router, path: []const u8) HandlerFn {
|
||||||
if (self.static_routes.get(path)) |rt| return rt.handler;
|
if (self.static_routes.get(path)) |rt| return rt.handler;
|
||||||
if (self.root_node.wildcard_child_node) |node| return node.handler;
|
if (self.root_node.wildcard_child_node) |node| return node.handler;
|
||||||
|
@ -187,6 +190,21 @@ pub const Listener = struct {
|
||||||
placeholder_children: std.ArrayList(*Node),
|
placeholder_children: std.ArrayList(*Node),
|
||||||
|
|
||||||
pub const Type = enum { normal, wildcard, placeholder };
|
pub const Type = enum { normal, wildcard, placeholder };
|
||||||
|
|
||||||
|
pub fn init(allocator: mem.Allocator) !*Node {
|
||||||
|
var self = try allocator.create(Node);
|
||||||
|
self.type = .normal;
|
||||||
|
self.max_depth = 256;
|
||||||
|
self.children = std.StringHashMap(*Node).init(allocator);
|
||||||
|
self.placeholder_children = std.ArrayList(*Node).init(allocator);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Node, allocator: mem.Allocator) void {
|
||||||
|
self.placeholder_children.deinit();
|
||||||
|
self.children.deinit();
|
||||||
|
allocator.destroy(self);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue