From 51307d973255e32ec1440083dee383e8b2cd8878 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Sat, 6 Jun 2026 07:57:50 +0200 Subject: Implement static handler and synchronous server handling --- src/http/handler.zig | 149 --------------------------------------------------- 1 file changed, 149 deletions(-) delete mode 100644 src/http/handler.zig (limited to 'src/http/handler.zig') diff --git a/src/http/handler.zig b/src/http/handler.zig deleted file mode 100644 index 2220fd0..0000000 --- a/src/http/handler.zig +++ /dev/null @@ -1,149 +0,0 @@ -const std = @import("std"); - -const Response = @import("Response.zig"); -const Route = @import("Route.zig"); -const Parameter = @import("Parameter.zig"); - -pub fn Context(comptime r: anytype) type { - return struct { - const route = Route.fromAny(r); - const Params = Parameter.Struct(route); - - const Request = struct { - base_request: *std.http.Server.Request, - params: Params, - arena: std.mem.Allocator, - gpa: std.mem.Allocator, - io: std.Io, - - /// Parses the body of the request and returns type `T`. - /// The arena allocator will be used to do the parsing. - pub fn json(self: @This(), T: type) !T { - var buffer: [1024]u8 = undefined; - var reader = std.json.Reader.init(self.arena, self.base_request.readerExpectNone(&buffer)); - return std.json.parseFromTokenSourceLeaky(T, self.arena, &reader, .{}); - } - }; - - const badRequest = struct { - pub fn badRequest(_: Request) Response { - return .with(.bad_request, .string("method does not exist")); - } - }.badRequest; - - get: *const fn (Request) Response = badRequest, - post: *const fn (Request) Response = badRequest, - delete: *const fn (Request) Response = badRequest, - head: *const fn (Request) Response = badRequest, - put: *const fn (Request) Response = badRequest, - connect: *const fn (Request) Response = badRequest, - options: *const fn (Request) Response = badRequest, - trace: *const fn (Request) Response = badRequest, - patch: *const fn (Request) Response = badRequest, - - pub fn handle( - self: *const @This(), - gpa: std.mem.Allocator, - arena: std.mem.Allocator, - io: std.Io, - request: *std.http.Server.Request, - ) Response { - const req: Request = .{ - .base_request = request, - .arena = arena, - .gpa = gpa, - .io = io, - .params = Parameter.parse(Params, &route, request.head.target), - }; - - return (switch (request.head.method) { - .GET => self.get, - .POST => self.post, - .DELETE => self.delete, - .HEAD => self.head, - .PUT => self.put, - .CONNECT => self.connect, - .OPTIONS => self.options, - .TRACE => self.trace, - .PATCH => self.patch, - })(req); - } - - pub fn interface(self: *const @This()) Interface { - return .from(self, route); - } - }; -} - -pub const Interface = struct { - route: Route, - base: *const anyopaque, - handler: *const fn ( - *const anyopaque, - std.mem.Allocator, - std.mem.Allocator, - std.Io, - *std.http.Server.Request, - ) Response, - - pub fn from(instance: anytype, route: Route) @This() { - const PtrT = @TypeOf(instance); - const func = struct { - pub fn handle( - base: *const anyopaque, - gpa: std.mem.Allocator, - arena: std.mem.Allocator, - io: std.Io, - request: *std.http.Server.Request, - ) Response { - return @as(PtrT, @ptrCast(@alignCast(base))).handle(gpa, arena, io, request); - } - }.handle; - - return .{ - .base = @ptrCast(instance), - .handler = func, - .route = route, - }; - } - - pub fn handle( - self: *const @This(), - gpa: std.mem.Allocator, - arena: std.mem.Allocator, - io: std.Io, - request: std.http.Server.Request, - ) Response { - return self.handler(self.base, gpa, arena, io, request); - } -}; - -test "interface" { - const M = struct { - const C = Context(.{ "api", "images", .id, "metadata" }); - const context: C = .{ - .post = post, - .get = get, - }; - - const Query = struct { - condition: []const u8, - start: usize, - length: usize, - }; - - fn post(request: C.Request) Response { - const query = request.json(Query) catch return .with(.bad_request, .void); - _ = query; - _ = request.params.id; - - return .ok(.string(request.params.id.as([]const u8))); - } - - fn get(request: C.Request) Response { - return .ok(Response.Message.file(request.io, "./some/path.txt") catch return .with(.not_found, .void)); - } - }; - - _ = M.context.interface(); -} -- cgit v1.2.3-70-g09d2