aboutsummaryrefslogtreecommitdiff
path: root/src/http/handler/context.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/handler/context.zig')
-rw-r--r--src/http/handler/context.zig76
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);
+ }
+ };
+}