diff options
Diffstat (limited to 'src/http/handler/context.zig')
| -rw-r--r-- | src/http/handler/context.zig | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/http/handler/context.zig b/src/http/handler/context.zig new file mode 100644 index 0000000..4e55446 --- /dev/null +++ b/src/http/handler/context.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const Response = @import("../Response.zig"); +const Route = @import("../Route.zig"); +const Parameter = @import("../Parameter.zig"); +const Interface = @import("Interface.zig"); + +pub fn Context(comptime r: anytype) type { + return struct { + pub const route = Route.fromAny(r); + pub const Params = Parameter.Struct(route); + + pub 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); + } + }; +} |