From 8892cae7dfe2d28fc0f0bd389755b594263a0d3e Mon Sep 17 00:00:00 2001 From: renerocksai Date: Mon, 8 Jan 2024 15:50:46 +0100 Subject: [PATCH] API cleanup #1 -------------- - EndpointListener.register() // was: addEndpoint - no more Simple - getEndpoint -> endpoint() --- README.md | 8 +- doc/authentication.md | 20 +- doc/why-no-errors.md | 4 +- examples/bindataformpost/bindataformpost.zig | 4 +- examples/cookies/cookies.zig | 4 +- examples/endpoint/main.zig | 21 +- examples/endpoint/stopendpoint.zig | 10 +- .../endpoint/{endpoint.zig => userweb.zig} | 56 ++--- examples/endpoint_auth/endpoint_auth.zig | 10 +- examples/hello/hello.zig | 6 +- examples/hello2/hello2.zig | 4 +- examples/hello_json/hello_json.zig | 4 +- examples/http_params/http_params.zig | 4 +- examples/https/https.zig | 6 +- examples/middleware/middleware.zig | 6 +- .../middleware_with_endpoint.zig | 18 +- examples/mustache/mustache.zig | 4 +- examples/routes/routes.zig | 14 +- examples/senderror/senderror.zig | 4 +- examples/sendfile/sendfile.zig | 4 +- examples/serve/serve.zig | 4 +- .../userpass_session_auth.zig | 14 +- examples/websockets/websockets.zig | 6 +- src/endpoint.zig | 205 +++++++++++++----- src/http_auth.zig | 16 +- src/middleware.zig | 22 +- src/tests/test_auth.zig | 52 ++--- src/tests/test_http_params.zig | 4 +- src/tests/test_sendfile.zig | 4 +- src/zap.zig | 61 +++--- wrk/zig/main.zig | 4 +- 31 files changed, 352 insertions(+), 251 deletions(-) rename examples/endpoint/{endpoint.zig => userweb.zig} (71%) diff --git a/README.md b/README.md index 6c5bac1..e06c28f 100644 --- a/README.md +++ b/README.md @@ -108,9 +108,9 @@ what's necessary to show a feature. less type-safe than `zap.Middleware`'s use of contexts. - [**Per Request Contexts**](./src/zap.zig#L102) : With the introduction of `setUserContext()` and `getUserContext()`, you can, of course use those two in - projects that don't use `zap.SimpleEndpoint` or `zap.Middleware`, too, if you + projects that don't use `zap.Endpoint` or `zap.Middleware`, too, if you really, really, absolutely don't find another way to solve your context - problem. **We recommend using a `zap.SimpleEndpoint`** inside of a struct that + problem. **We recommend using a `zap.Endpoint`** inside of a struct that can provide all the context you need **instead**. You get access to your struct in the callbacks via the `@fieldParentPtr()` trick that is used extensively in Zap's examples, like the [endpoint @@ -369,7 +369,7 @@ $ zig build run-routes const std = @import("std"); const zap = @import("zap"); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if (r.path) |the_path| { std.debug.print("PATH: {s}\n", .{the_path}); } @@ -381,7 +381,7 @@ fn on_request(r: zap.SimpleRequest) void { } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request, .log = true, diff --git a/doc/authentication.md b/doc/authentication.md index 931b7e5..313a827 100644 --- a/doc/authentication.md +++ b/doc/authentication.md @@ -12,7 +12,7 @@ For convenience, Authenticator types exist that can authenticate requests. Zap also provides an `AuthenticatingEndpoint` endpoint-wrapper. Have a look at the [example](../examples/endpoint_auth) and the [tests](../src/tests/test_auth.zig). The following describes the Authenticator types. All of them provide the -`authenticateRequest()` function, which takes a `zap.SimpleRequest` and returns +`authenticateRequest()` function, which takes a `zap.Request` and returns a bool value whether it could be authenticated or not. Further down, we show how to use the Authenticators, and also the @@ -60,7 +60,7 @@ var auth = try zap.BearerAuthSingle.init(allocator, token, null); defer auth.deinit(); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if(authenticator.authenticateRequest(r)) { r.sendBody( \\ @@ -94,7 +94,7 @@ var auth = try zap.BearerAuthMulti(Set).init(allocator, &set, null); defer auth.deinit(); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if(authenticator.authenticateRequest(r)) { r.sendBody( \\ @@ -132,7 +132,7 @@ var auth = try Authenticator.init(a, &map, null); defer auth.deinit(); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if(authenticator.authenticateRequest(r)) { r.sendBody( \\ @@ -168,7 +168,7 @@ var auth = try Authenticator.init(allocator, &set, null); defer auth.deinit(); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if(authenticator.authenticateRequest(r)) { r.sendBody( \\ @@ -206,13 +206,13 @@ const HTTP_RESPONSE: []const u8 = ; // authenticated requests go here -fn endpoint_http_get(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { +fn endpoint_http_get(e: *zap.Endpoint, r: zap.Request) void { _ = e; r.sendBody(HTTP_RESPONSE) catch return; } // just for fun, we also catch the unauthorized callback -fn endpoint_http_unauthorized(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { +fn endpoint_http_unauthorized(e: *zap.Endpoint, r: zap.Request) void { _ = e; r.setStatus(.unauthorized); r.sendBody("UNAUTHORIZED ACCESS") catch return; @@ -220,7 +220,7 @@ fn endpoint_http_unauthorized(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void pub fn main() !void { // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -233,7 +233,7 @@ pub fn main() !void { defer listener.deinit(); // create mini endpoint - var ep = zap.SimpleEndpoint.init(.{ + var ep = zap.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -248,7 +248,7 @@ pub fn main() !void { const BearerAuthEndpoint = zap.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; std.debug.print( diff --git a/doc/why-no-errors.md b/doc/why-no-errors.md index db80377..17fffd4 100644 --- a/doc/why-no-errors.md +++ b/doc/why-no-errors.md @@ -58,14 +58,14 @@ Now that I think I've made my point 😊, you can, of course always do the following: ```zig -fn on_request_with_errors(r: zap.SimpleHttpRequest) !void { +fn on_request_with_errors(r: zap.HttpRequest) !void { // do all the try stuff here } ``` ```zig // THIS IS WHAT YOU PASS TO THE LISTENER / ENDPONT / ... -fn on_request(r: zap.SimpleHttpRequest) void { +fn on_request(r: zap.HttpRequest) void { on_request_with_errors(r) catch |err| { // log the error or use: return r.returnWithErrorStackTrace(err); diff --git a/examples/bindataformpost/bindataformpost.zig b/examples/bindataformpost/bindataformpost.zig index 44f6a8e..c9e33f2 100644 --- a/examples/bindataformpost/bindataformpost.zig +++ b/examples/bindataformpost/bindataformpost.zig @@ -4,7 +4,7 @@ const zap = @import("zap"); const Handler = struct { var alloc: std.mem.Allocator = undefined; - pub fn on_request(r: zap.SimpleRequest) void { + pub fn on_request(r: zap.Request) void { // check for FORM parameters r.parseBody() catch |err| { std.log.err("Parse Body error: {any}. Expected if body is empty", .{err}); @@ -92,7 +92,7 @@ pub fn main() !void { Handler.alloc = allocator; // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3000, .on_request = Handler.on_request, diff --git a/examples/cookies/cookies.zig b/examples/cookies/cookies.zig index 9fba109..88ef889 100644 --- a/examples/cookies/cookies.zig +++ b/examples/cookies/cookies.zig @@ -33,7 +33,7 @@ pub fn main() !void { const Handler = struct { var alloc: std.mem.Allocator = undefined; - pub fn on_request(r: zap.SimpleRequest) void { + pub fn on_request(r: zap.Request) void { std.debug.print("\n=====================================================\n", .{}); defer std.debug.print("=====================================================\n\n", .{}); @@ -98,7 +98,7 @@ pub fn main() !void { Handler.alloc = allocator; // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3000, .on_request = Handler.on_request, diff --git a/examples/endpoint/main.zig b/examples/endpoint/main.zig index c387d94..a41daa5 100644 --- a/examples/endpoint/main.zig +++ b/examples/endpoint/main.zig @@ -1,10 +1,10 @@ const std = @import("std"); const zap = @import("zap"); -const Endpoint = @import("endpoint.zig"); +const UserWeb = @import("userweb.zig"); const StopEndpoint = @import("stopendpoint.zig"); // this is just to demo that we can catch arbitrary slugs -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if (r.path) |the_path| { std.debug.print("REQUESTED PATH: {s}\n", .{the_path}); } @@ -21,7 +21,7 @@ pub fn main() !void { // we scope everything that can allocate within this block for leak detection { // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( allocator, .{ .port = 3000, @@ -34,19 +34,20 @@ pub fn main() !void { ); defer listener.deinit(); - var endpoint = Endpoint.init(allocator, "/users"); - defer endpoint.deinit(); + // /users endpoint + var userWeb = UserWeb.init(allocator, "/users"); + defer userWeb.deinit(); var stopEp = StopEndpoint.init("/stop"); - // add endpoint - try listener.addEndpoint(endpoint.getUserEndpoint()); - try listener.addEndpoint(stopEp.getEndpoint()); + // register endpoints with the listener + try listener.register(userWeb.endpoint()); + try listener.register(stopEp.endpoint()); // fake some users var uid: usize = undefined; - uid = try endpoint.getUsers().addByName("renerocksai", null); - uid = try endpoint.getUsers().addByName("renerocksai", "your mom"); + uid = try userWeb.users().addByName("renerocksai", null); + uid = try userWeb.users().addByName("renerocksai", "your mom"); // listen try listener.listen(); diff --git a/examples/endpoint/stopendpoint.zig b/examples/endpoint/stopendpoint.zig index 2735074..9411d49 100644 --- a/examples/endpoint/stopendpoint.zig +++ b/examples/endpoint/stopendpoint.zig @@ -5,24 +5,24 @@ const zap = @import("zap"); /// the main thread usually continues at the instructions after the call to zap.start(). pub const Self = @This(); -endpoint: zap.SimpleEndpoint = undefined, +ep: zap.Endpoint = undefined, pub fn init( path: []const u8, ) Self { return .{ - .endpoint = zap.SimpleEndpoint.init(.{ + .ep = zap.Endpoint.init(.{ .path = path, .get = get, }), }; } -pub fn getEndpoint(self: *Self) *zap.SimpleEndpoint { - return &self.endpoint; +pub fn endpoint(self: *Self) *zap.Endpoint { + return &self.ep; } -fn get(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { +fn get(e: *zap.Endpoint, r: zap.Request) void { _ = e; _ = r; zap.stop(); diff --git a/examples/endpoint/endpoint.zig b/examples/endpoint/userweb.zig similarity index 71% rename from examples/endpoint/endpoint.zig rename to examples/endpoint/userweb.zig index 6fb16bd..ca11a6a 100644 --- a/examples/endpoint/endpoint.zig +++ b/examples/endpoint/userweb.zig @@ -8,8 +8,8 @@ const User = Users.User; pub const Self = @This(); alloc: std.mem.Allocator = undefined, -endpoint: zap.SimpleEndpoint = undefined, -users: Users = undefined, +ep: zap.Endpoint = undefined, +_users: Users = undefined, pub fn init( a: std.mem.Allocator, @@ -17,8 +17,8 @@ pub fn init( ) Self { return .{ .alloc = a, - .users = Users.init(a), - .endpoint = zap.SimpleEndpoint.init(.{ + ._users = Users.init(a), + .ep = zap.Endpoint.init(.{ .path = user_path, .get = getUser, .post = postUser, @@ -31,30 +31,30 @@ pub fn init( } pub fn deinit(self: *Self) void { - self.users.deinit(); + self._users.deinit(); } -pub fn getUsers(self: *Self) *Users { - return &self.users; +pub fn users(self: *Self) *Users { + return &self._users; } -pub fn getUserEndpoint(self: *Self) *zap.SimpleEndpoint { - return &self.endpoint; +pub fn endpoint(self: *Self) *zap.Endpoint { + return &self.ep; } fn userIdFromPath(self: *Self, path: []const u8) ?usize { - if (path.len >= self.endpoint.settings.path.len + 2) { - if (path[self.endpoint.settings.path.len] != '/') { + if (path.len >= self.ep.settings.path.len + 2) { + if (path[self.ep.settings.path.len] != '/') { return null; } - const idstr = path[self.endpoint.settings.path.len + 1 ..]; + const idstr = path[self.ep.settings.path.len + 1 ..]; return std.fmt.parseUnsigned(usize, idstr, 10) catch null; } return null; } -fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - const self = @fieldParentPtr(Self, "endpoint", e); +fn getUser(e: *zap.Endpoint, r: zap.Request) void { + const self = @fieldParentPtr(Self, "ep", e); if (r.path) |path| { // /users if (path.len == e.settings.path.len) { @@ -62,7 +62,7 @@ fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { } var jsonbuf: [256]u8 = undefined; if (self.userIdFromPath(path)) |id| { - if (self.users.get(id)) |user| { + if (self._users.get(id)) |user| { if (zap.stringifyBuf(&jsonbuf, user, .{})) |json| { r.sendJson(json) catch return; } @@ -71,8 +71,8 @@ fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { } } -fn listUsers(self: *Self, r: zap.SimpleRequest) void { - if (self.users.toJSON()) |json| { +fn listUsers(self: *Self, r: zap.Request) void { + if (self._users.toJSON()) |json| { defer self.alloc.free(json); r.sendJson(json) catch return; } else |err| { @@ -80,13 +80,13 @@ fn listUsers(self: *Self, r: zap.SimpleRequest) void { } } -fn postUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - const self = @fieldParentPtr(Self, "endpoint", e); +fn postUser(e: *zap.Endpoint, r: zap.Request) void { + const self = @fieldParentPtr(Self, "ep", e); if (r.body) |body| { var maybe_user: ?std.json.Parsed(User) = std.json.parseFromSlice(User, self.alloc, body, .{}) catch null; if (maybe_user) |u| { defer u.deinit(); - if (self.users.addByName(u.value.first_name, u.value.last_name)) |id| { + if (self._users.addByName(u.value.first_name, u.value.last_name)) |id| { var jsonbuf: [128]u8 = undefined; if (zap.stringifyBuf(&jsonbuf, .{ .status = "OK", .id = id }, .{})) |json| { r.sendJson(json) catch return; @@ -99,17 +99,17 @@ fn postUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { } } -fn putUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - const self = @fieldParentPtr(Self, "endpoint", e); +fn putUser(e: *zap.Endpoint, r: zap.Request) void { + const self = @fieldParentPtr(Self, "ep", e); if (r.path) |path| { if (self.userIdFromPath(path)) |id| { - if (self.users.get(id)) |_| { + if (self._users.get(id)) |_| { if (r.body) |body| { var maybe_user: ?std.json.Parsed(User) = std.json.parseFromSlice(User, self.alloc, body, .{}) catch null; if (maybe_user) |u| { defer u.deinit(); var jsonbuf: [128]u8 = undefined; - if (self.users.update(id, u.value.first_name, u.value.last_name)) { + if (self._users.update(id, u.value.first_name, u.value.last_name)) { if (zap.stringifyBuf(&jsonbuf, .{ .status = "OK", .id = id }, .{})) |json| { r.sendJson(json) catch return; } @@ -125,12 +125,12 @@ fn putUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { } } -fn deleteUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - const self = @fieldParentPtr(Self, "endpoint", e); +fn deleteUser(e: *zap.Endpoint, r: zap.Request) void { + const self = @fieldParentPtr(Self, "ep", e); if (r.path) |path| { if (self.userIdFromPath(path)) |id| { var jsonbuf: [128]u8 = undefined; - if (self.users.delete(id)) { + if (self._users.delete(id)) { if (zap.stringifyBuf(&jsonbuf, .{ .status = "OK", .id = id }, .{})) |json| { r.sendJson(json) catch return; } @@ -143,7 +143,7 @@ fn deleteUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { } } -fn optionsUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { +fn optionsUser(e: *zap.Endpoint, r: zap.Request) void { _ = e; r.setHeader("Access-Control-Allow-Origin", "*") catch return; r.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") catch return; diff --git a/examples/endpoint_auth/endpoint_auth.zig b/examples/endpoint_auth/endpoint_auth.zig index b6056c1..3c0f19e 100644 --- a/examples/endpoint_auth/endpoint_auth.zig +++ b/examples/endpoint_auth/endpoint_auth.zig @@ -11,13 +11,13 @@ const HTTP_RESPONSE: []const u8 = ; // authenticated requests go here -fn endpoint_http_get(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { +fn endpoint_http_get(e: *zap.Endpoint, r: zap.Request) void { _ = e; r.sendBody(HTTP_RESPONSE) catch return; } // just for fun, we also catch the unauthorized callback -fn endpoint_http_unauthorized(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { +fn endpoint_http_unauthorized(e: *zap.Endpoint, r: zap.Request) void { _ = e; r.setStatus(.unauthorized); r.sendBody("UNAUTHORIZED ACCESS") catch return; @@ -25,7 +25,7 @@ fn endpoint_http_unauthorized(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void pub fn main() !void { // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -38,7 +38,7 @@ pub fn main() !void { defer listener.deinit(); // create mini endpoint - var ep = zap.SimpleEndpoint.init(.{ + var ep = zap.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -53,7 +53,7 @@ pub fn main() !void { const BearerAuthEndpoint = zap.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; std.debug.print( diff --git a/examples/hello/hello.zig b/examples/hello/hello.zig index 738e345..8b0f760 100644 --- a/examples/hello/hello.zig +++ b/examples/hello/hello.zig @@ -1,7 +1,7 @@ const std = @import("std"); const zap = @import("zap"); -fn on_request_verbose(r: zap.SimpleRequest) void { +fn on_request_verbose(r: zap.Request) void { if (r.path) |the_path| { std.debug.print("PATH: {s}\n", .{the_path}); } @@ -12,12 +12,12 @@ fn on_request_verbose(r: zap.SimpleRequest) void { r.sendBody("

Hello from ZAP!!!

") catch return; } -fn on_request_minimal(r: zap.SimpleRequest) void { +fn on_request_minimal(r: zap.Request) void { r.sendBody("

Hello from ZAP!!!

") catch return; } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request_verbose, .log = true, diff --git a/examples/hello2/hello2.zig b/examples/hello2/hello2.zig index 75afaf0..5e7fa9a 100644 --- a/examples/hello2/hello2.zig +++ b/examples/hello2/hello2.zig @@ -1,7 +1,7 @@ const std = @import("std"); const zap = @import("zap"); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { const m = r.method orelse ""; const p = r.path orelse "/"; const qm = if (r.query) |_| "?" else ""; @@ -35,7 +35,7 @@ fn on_request(r: zap.SimpleRequest) void { } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request, .log = false, diff --git a/examples/hello_json/hello_json.zig b/examples/hello_json/hello_json.zig index b477230..8cd348c 100644 --- a/examples/hello_json/hello_json.zig +++ b/examples/hello_json/hello_json.zig @@ -6,7 +6,7 @@ const User = struct { last_name: ?[]const u8 = null, }; -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { if (!std.mem.eql(u8, r.method.?, "GET")) return; @@ -43,7 +43,7 @@ fn setupUserData(a: std.mem.Allocator) !void { pub fn main() !void { var a = std.heap.page_allocator; try setupUserData(a); - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request, .log = false, diff --git a/examples/http_params/http_params.zig b/examples/http_params/http_params.zig index 48d0f12..f8aa441 100644 --- a/examples/http_params/http_params.zig +++ b/examples/http_params/http_params.zig @@ -32,7 +32,7 @@ pub fn main() !void { const Handler = struct { var alloc: std.mem.Allocator = undefined; - pub fn on_request(r: zap.SimpleRequest) void { + pub fn on_request(r: zap.Request) void { std.debug.print("\n=====================================================\n", .{}); defer std.debug.print("=====================================================\n\n", .{}); @@ -98,7 +98,7 @@ pub fn main() !void { Handler.alloc = allocator; // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3000, .on_request = Handler.on_request, diff --git a/examples/https/https.zig b/examples/https/https.zig index d6e4000..88c53a7 100644 --- a/examples/https/https.zig +++ b/examples/https/https.zig @@ -1,7 +1,7 @@ const std = @import("std"); const zap = @import("zap"); -fn on_request_verbose(r: zap.SimpleRequest) void { +fn on_request_verbose(r: zap.Request) void { if (r.path) |the_path| { std.debug.print("PATH: {s}\n", .{the_path}); } @@ -12,7 +12,7 @@ fn on_request_verbose(r: zap.SimpleRequest) void { r.sendBody("

Hello from ZAP!!!

") catch return; } -fn on_request_minimal(r: zap.SimpleRequest) void { +fn on_request_minimal(r: zap.Request) void { r.sendBody("

Hello from ZAP!!!

") catch return; } @@ -51,7 +51,7 @@ pub fn main() !void { }); defer tls.deinit(); - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 4443, .on_request = on_request_verbose, .log = true, diff --git a/examples/middleware/middleware.zig b/examples/middleware/middleware.zig index 6b4983e..5687f93 100644 --- a/examples/middleware/middleware.zig +++ b/examples/middleware/middleware.zig @@ -69,7 +69,7 @@ const UserMiddleWare = struct { } // note that the first parameter is of type *Handler, not *Self !!! - pub fn onRequest(handler: *Handler, r: zap.SimpleRequest, context: *Context) bool { + pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { // this is how we would get our self pointer var self = @fieldParentPtr(Self, "handler", handler); @@ -113,7 +113,7 @@ const SessionMiddleWare = struct { } // note that the first parameter is of type *Handler, not *Self !!! - pub fn onRequest(handler: *Handler, r: zap.SimpleRequest, context: *Context) bool { + pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { // this is how we would get our self pointer var self = @fieldParentPtr(Self, "handler", handler); _ = self; @@ -148,7 +148,7 @@ const HtmlMiddleWare = struct { } // note that the first parameter is of type *Handler, not *Self !!! - pub fn onRequest(handler: *Handler, r: zap.SimpleRequest, context: *Context) bool { + pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { // this is how we would get our self pointer var self = @fieldParentPtr(Self, "handler", handler); diff --git a/examples/middleware_with_endpoint/middleware_with_endpoint.zig b/examples/middleware_with_endpoint/middleware_with_endpoint.zig index f22397f..e9b5e2d 100644 --- a/examples/middleware_with_endpoint/middleware_with_endpoint.zig +++ b/examples/middleware_with_endpoint/middleware_with_endpoint.zig @@ -56,7 +56,7 @@ const UserMiddleWare = struct { } // note that the first parameter is of type *Handler, not *Self !!! - pub fn onRequest(handler: *Handler, r: zap.SimpleRequest, context: *Context) bool { + pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { // this is how we would get our self pointer var self = @fieldParentPtr(Self, "handler", handler); @@ -102,7 +102,7 @@ const SessionMiddleWare = struct { } // note that the first parameter is of type *Handler, not *Self !!! - pub fn onRequest(handler: *Handler, r: zap.SimpleRequest, context: *Context) bool { + pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { // this is how we would get our self pointer var self = @fieldParentPtr(Self, "handler", handler); _ = self; @@ -137,24 +137,24 @@ const SessionMiddleWare = struct { // parameter. // const HtmlEndpoint = struct { - endpoint: zap.SimpleEndpoint = undefined, + ep: zap.Endpoint = undefined, const Self = @This(); pub fn init() Self { return .{ - .endpoint = zap.SimpleEndpoint.init(.{ + .ep = zap.Endpoint.init(.{ .path = "/doesn'tmatter", .get = get, }), }; } - pub fn getEndpoint(self: *Self) *zap.SimpleEndpoint { - return &self.endpoint; + pub fn endpoint(self: *Self) *zap.Endpoint { + return &self.ep; } - pub fn get(ep: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - var self = @fieldParentPtr(Self, "endpoint", ep); + pub fn get(ep: *zap.Endpoint, r: zap.Request) void { + const self = @fieldParentPtr(Self, "ep", ep); _ = self; var buf: [1024]u8 = undefined; @@ -207,7 +207,7 @@ pub fn main() !void { // we wrap the endpoint with a middleware handler var htmlHandler = zap.Middleware.EndpointHandler(Handler, Context).init( - htmlEndpoint.getEndpoint(), // the endpoint + htmlEndpoint.endpoint(), // the endpoint null, // no other handler (we are the last in the chain) true, // break on finish. See EndpointHandler for this. Not applicable here. ); diff --git a/examples/mustache/mustache.zig b/examples/mustache/mustache.zig index a254c35..26dd6d9 100644 --- a/examples/mustache/mustache.zig +++ b/examples/mustache/mustache.zig @@ -2,7 +2,7 @@ const std = @import("std"); const zap = @import("zap"); const Mustache = @import("zap").Mustache; -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { const template = \\ {{=<< >>=}} \\ * Users: @@ -49,7 +49,7 @@ fn on_request(r: zap.SimpleRequest) void { } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request, .log = true, diff --git a/examples/routes/routes.zig b/examples/routes/routes.zig index 5c4e7bd..43222d1 100644 --- a/examples/routes/routes.zig +++ b/examples/routes/routes.zig @@ -1,7 +1,9 @@ const std = @import("std"); const zap = @import("zap"); -fn dispatch_routes(r: zap.SimpleRequest) void { +// NOTE: this is a super simplified example, just using a hashmap to map +// from HTTP path to request function. +fn dispatch_routes(r: zap.Request) void { // dispatch if (r.path) |the_path| { if (routes.get(the_path)) |foo| { @@ -20,12 +22,12 @@ fn dispatch_routes(r: zap.SimpleRequest) void { ) catch return; } -fn static_site(r: zap.SimpleRequest) void { +fn static_site(r: zap.Request) void { r.sendBody("

Hello from STATIC ZAP!

") catch return; } var dynamic_counter: i32 = 0; -fn dynamic_site(r: zap.SimpleRequest) void { +fn dynamic_site(r: zap.Request) void { dynamic_counter += 1; var buf: [128]u8 = undefined; const filled_buf = std.fmt.bufPrintZ( @@ -37,16 +39,16 @@ fn dynamic_site(r: zap.SimpleRequest) void { } fn setup_routes(a: std.mem.Allocator) !void { - routes = std.StringHashMap(zap.SimpleHttpRequestFn).init(a); + routes = std.StringHashMap(zap.HttpRequestFn).init(a); try routes.put("/static", static_site); try routes.put("/dynamic", dynamic_site); } -var routes: std.StringHashMap(zap.SimpleHttpRequestFn) = undefined; +var routes: std.StringHashMap(zap.HttpRequestFn) = undefined; pub fn main() !void { try setup_routes(std.heap.page_allocator); - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = dispatch_routes, .log = true, diff --git a/examples/senderror/senderror.zig b/examples/senderror/senderror.zig index 32addd9..9a2fe73 100644 --- a/examples/senderror/senderror.zig +++ b/examples/senderror/senderror.zig @@ -5,14 +5,14 @@ fn MAKE_MEGA_ERROR() !void { return error.MEGA_ERROR; } -fn MY_REQUEST_HANDLER(r: zap.SimpleRequest) void { +fn MY_REQUEST_HANDLER(r: zap.Request) void { MAKE_MEGA_ERROR() catch |err| { r.sendError(err, 505); }; } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = MY_REQUEST_HANDLER, .log = true, diff --git a/examples/sendfile/sendfile.zig b/examples/sendfile/sendfile.zig index b7099e7..4c97309 100644 --- a/examples/sendfile/sendfile.zig +++ b/examples/sendfile/sendfile.zig @@ -6,7 +6,7 @@ var read_len: ?usize = null; const testfile = @embedFile("testfile.txt"); -pub fn on_request(r: zap.SimpleRequest) void { +pub fn on_request(r: zap.Request) void { // Sends a file if present in the filesystem orelse returns an error. // // - efficiently sends a file using gzip compression @@ -27,7 +27,7 @@ pub fn on_request(r: zap.SimpleRequest) void { pub fn main() !void { // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3000, .on_request = on_request, diff --git a/examples/serve/serve.zig b/examples/serve/serve.zig index 117e553..d9f9d65 100644 --- a/examples/serve/serve.zig +++ b/examples/serve/serve.zig @@ -1,13 +1,13 @@ const std = @import("std"); const zap = @import("zap"); -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { r.setStatus(.not_found); r.sendBody("

404 - File not found

") catch return; } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request, .public_folder = "examples/serve", diff --git a/examples/userpass_session_auth/userpass_session_auth.zig b/examples/userpass_session_auth/userpass_session_auth.zig index 5de5e05..0880eb2 100644 --- a/examples/userpass_session_auth/userpass_session_auth.zig +++ b/examples/userpass_session_auth/userpass_session_auth.zig @@ -20,17 +20,17 @@ const loginpage = @embedFile("html/login.html"); const img = @embedFile("./html/Ziggy_the_Ziguana.svg.png"); // global vars yeah! -// in bigger projects, we'd probably make use of zap.SimpleEndpoint or +// in bigger projects, we'd probably make use of zap.Endpoint or // zap.Middleware and "hide" stuff like authenticators in there var authenticator: Authenticator = undefined; // the login page (embedded) -fn on_login(r: zap.SimpleRequest) void { +fn on_login(r: zap.Request) void { r.sendBody(loginpage) catch return; } // the "normal page" -fn on_normal_page(r: zap.SimpleRequest) void { +fn on_normal_page(r: zap.Request) void { zap.debug("on_normal_page()\n", .{}); r.sendBody( \\ @@ -42,7 +42,7 @@ fn on_normal_page(r: zap.SimpleRequest) void { } // the logged-out page -fn on_logout(r: zap.SimpleRequest) void { +fn on_logout(r: zap.Request) void { zap.debug("on_logout()\n", .{}); authenticator.logout(&r); // note, the link below doesn't matter as the authenticator will send us @@ -56,7 +56,7 @@ fn on_logout(r: zap.SimpleRequest) void { ) catch return; } -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { switch (authenticator.authenticateRequest(&r)) { .Handled => { // the authenticator handled the entire request for us. @@ -123,8 +123,8 @@ pub fn main() !void { // we start a block here so the defers will run before we call the gpa // to detect leaks { - var allocator = gpa.allocator(); - var listener = zap.SimpleHttpListener.init(.{ + const allocator = gpa.allocator(); + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request, .log = true, diff --git a/examples/websockets/websockets.zig b/examples/websockets/websockets.zig index 09975bb..06b1b17 100644 --- a/examples/websockets/websockets.zig +++ b/examples/websockets/websockets.zig @@ -162,7 +162,7 @@ fn handle_websocket_message( // // HTTP stuff // -fn on_request(r: zap.SimpleRequest) void { +fn on_request(r: zap.Request) void { r.setHeader("Server", "zap.example") catch unreachable; r.sendBody( \\ @@ -171,7 +171,7 @@ fn on_request(r: zap.SimpleRequest) void { ) catch return; } -fn on_upgrade(r: zap.SimpleRequest, target_protocol: []const u8) void { +fn on_upgrade(r: zap.Request, target_protocol: []const u8) void { // make sure we're talking the right protocol if (!std.mem.eql(u8, target_protocol, "websocket")) { std.log.warn("received illegal protocol: {s}", .{target_protocol}); @@ -207,7 +207,7 @@ pub fn main() !void { defer GlobalContextManager.deinit(); // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3010, .on_request = on_request, diff --git a/src/endpoint.zig b/src/endpoint.zig index a04f7f6..1d05091 100644 --- a/src/endpoint.zig +++ b/src/endpoint.zig @@ -2,29 +2,86 @@ const std = @import("std"); const zap = @import("zap.zig"); const auth = @import("http_auth.zig"); -const Request = zap.SimpleRequest; -const ListenerSettings = zap.SimpleHttpListenerSettings; -const Listener = zap.SimpleHttpListener; +// zap types +const Request = zap.Request; +const ListenerSettings = zap.HttpListenerSettings; +const Listener = zap.HttpListener; -pub const RequestFn = *const fn (self: *SimpleEndpoint, r: Request) void; -pub const SimpleEndpointSettings = struct { +/// Type of the request function callbacks. +pub const RequestFn = *const fn (self: *Endpoint, r: Request) void; + +/// Settings to initialize an Endpoint +pub const EndpointSettings = struct { + /// path / slug of the endpoint path: []const u8, + /// callback to GET request handler get: ?RequestFn = null, + /// callback to POST request handler post: ?RequestFn = null, + /// callback to PUT request handler put: ?RequestFn = null, + /// callback to DELETE request handler delete: ?RequestFn = null, + /// callback to PATCH request handler patch: ?RequestFn = null, + /// callback to OPTIONS request handler options: ?RequestFn = null, - /// only applicable to AuthenticatingEndpoint + /// Only applicable to AuthenticatingEndpoint: handler for unauthorized requests unauthorized: ?RequestFn = null, }; -pub const SimpleEndpoint = struct { - settings: SimpleEndpointSettings, +/// The simple Endpoint struct. Create one and pass in your callbacks. Then, +/// pass it to a HttpListener's `register()` function to register with the +/// listener. +/// +/// **NOTE**: A common endpoint pattern for zap is to create your own struct +/// that embeds an Endpoint, provides specific callbacks, and uses +/// `@fieldParentPtr` to get a reference to itself. +/// +/// Example: +/// A simple endpoint listening on the /stop route that shuts down zap. +/// The main thread usually continues at the instructions after the call to zap.start(). +/// +/// ```zig +/// // file: stopendpoint.zig +/// +/// pub const Self = @This(); +/// +/// ep: zap.Endpoint = undefined, +/// +/// pub fn init( +/// path: []const u8, +/// ) Self { +/// return .{ +/// .ep = zap.Endpoint.init(.{ +/// .path = path, +/// .get = get, +/// }), +/// }; +/// } +/// +/// // access the internal Endpoint +/// pub fn endpoint(self: *Self) *zap.Endpoint { +/// return &self.ep; +/// } +/// +/// fn get(e: *zap.Endpoint, r: zap.Request) void { +/// const self: *Self = @fieldParentPtr(Self, "ep", e); +/// _ = self; +/// _ = e; +/// _ = r; +/// zap.stop(); +/// } +/// ``` +pub const Endpoint = struct { + settings: EndpointSettings, const Self = @This(); - pub fn init(s: SimpleEndpointSettings) Self { + /// Initialize the endpoint. + /// Set only the callbacks you need. Requests of HTTP methods without a + /// provided callback will be ignored. + pub fn init(s: EndpointSettings) Self { return .{ .settings = .{ .path = s.path, @@ -39,12 +96,14 @@ pub const SimpleEndpoint = struct { }; } - fn nop(self: *SimpleEndpoint, r: Request) void { + // no operation. Dummy handler function for ignoring unset request types. + fn nop(self: *Endpoint, r: Request) void { _ = self; _ = r; } - pub fn onRequest(self: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// The global request handler for this Endpoint, called by the listener. + pub fn onRequest(self: *Endpoint, r: zap.Request) void { if (r.method) |m| { if (std.mem.eql(u8, m, "GET")) return self.settings.get.?(self, r); @@ -62,19 +121,23 @@ pub const SimpleEndpoint = struct { } }; -/// Wrap an endpoint with an authenticator +/// Wrap an endpoint with an Authenticator -> new Endpoint of type Endpoint +/// is available via the `endpoint()` function. pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return struct { authenticator: *Authenticator, - endpoint: *SimpleEndpoint, - auth_endpoint: SimpleEndpoint, + ep: *Endpoint, + auth_endpoint: Endpoint, const Self = @This(); - pub fn init(e: *SimpleEndpoint, authenticator: *Authenticator) Self { + /// Init the authenticating endpoint. Pass in a pointer to the endpoint + /// you want to wrap, and the Authenticator that takes care of authenticating + /// requests. + pub fn init(e: *Endpoint, authenticator: *Authenticator) Self { return .{ .authenticator = authenticator, - .endpoint = e, - .auth_endpoint = SimpleEndpoint.init(.{ + .ep = e, + .auth_endpoint = Endpoint.init(.{ .path = e.settings.path, // we override only the set ones. the other ones // are set to null anyway -> will be nopped out @@ -89,20 +152,21 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { }; } - /// get the auth endpoint struct so we can be stored in the listener - /// when the listener calls the auth_endpoint, onRequest will have - /// access to all of us via fieldParentPtr - pub fn getEndpoint(self: *Self) *SimpleEndpoint { + /// Get the auth endpoint struct of type Endpoint so it can be stored in the listener. + /// When the listener calls the auth_endpoint, onRequest will have + /// access to all of this via fieldParentPtr + pub fn endpoint(self: *Self) *Endpoint { return &self.auth_endpoint; } - /// here, the auth_endpoint will be passed in - pub fn get(e: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// GET: here, the auth_endpoint will be passed in as endpoint. + /// Authenticates GET requests using the Authenticator. + pub fn get(e: *Endpoint, r: zap.Request) void { const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); switch (authEp.authenticator.authenticateRequest(&r)) { .AuthFailed => { if (e.settings.unauthorized) |unauthorized| { - unauthorized(authEp.endpoint, r); + unauthorized(authEp.ep, r); return; } else { r.setStatus(.unauthorized); @@ -110,18 +174,19 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return; } }, - .AuthOK => authEp.endpoint.settings.get.?(authEp.endpoint, r), + .AuthOK => authEp.ep.settings.get.?(authEp.ep, r), .Handled => {}, } } - /// here, the auth_endpoint will be passed in - pub fn post(e: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// POST: here, the auth_endpoint will be passed in as endpoint. + /// Authenticates POST requests using the Authenticator. + pub fn post(e: *Endpoint, r: zap.Request) void { const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); switch (authEp.authenticator.authenticateRequest(&r)) { .AuthFailed => { if (e.settings.unauthorized) |unauthorized| { - unauthorized(authEp.endpoint, r); + unauthorized(authEp.ep, r); return; } else { r.setStatus(.unauthorized); @@ -129,18 +194,19 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return; } }, - .AuthOK => authEp.endpoint.settings.post.?(authEp.endpoint, r), + .AuthOK => authEp.ep.settings.post.?(authEp.ep, r), .Handled => {}, } } - /// here, the auth_endpoint will be passed in - pub fn put(e: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// PUT: here, the auth_endpoint will be passed in as endpoint. + /// Authenticates PUT requests using the Authenticator. + pub fn put(e: *Endpoint, r: zap.Request) void { const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); switch (authEp.authenticator.authenticateRequest(&r)) { .AuthFailed => { if (e.settings.unauthorized) |unauthorized| { - unauthorized(authEp.endpoint, r); + unauthorized(authEp.ep, r); return; } else { r.setStatus(.unauthorized); @@ -148,18 +214,19 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return; } }, - .AuthOK => authEp.endpoint.settings.put.?(authEp.endpoint, r), + .AuthOK => authEp.ep.settings.put.?(authEp.ep, r), .Handled => {}, } } - /// here, the auth_endpoint will be passed in - pub fn delete(e: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// DELETE: here, the auth_endpoint will be passed in as endpoint. + /// Authenticates DELETE requests using the Authenticator. + pub fn delete(e: *Endpoint, r: zap.Request) void { const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); switch (authEp.authenticator.authenticateRequest(&r)) { .AuthFailed => { if (e.settings.unauthorized) |unauthorized| { - unauthorized(authEp.endpoint, r); + unauthorized(authEp.ep, r); return; } else { r.setStatus(.unauthorized); @@ -167,18 +234,19 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return; } }, - .AuthOK => authEp.endpoint.settings.delete.?(authEp.endpoint, r), + .AuthOK => authEp.ep.settings.delete.?(authEp.ep, r), .Handled => {}, } } - /// here, the auth_endpoint will be passed in - pub fn patch(e: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// PATCH: here, the auth_endpoint will be passed in as endpoint. + /// Authenticates PATCH requests using the Authenticator. + pub fn patch(e: *Endpoint, r: zap.Request) void { const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); switch (authEp.authenticator.authenticateRequest(&r)) { .AuthFailed => { if (e.settings.unauthorized) |unauthorized| { - unauthorized(authEp.endpoint, r); + unauthorized(authEp.ep, r); return; } else { r.setStatus(.unauthorized); @@ -186,18 +254,19 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return; } }, - .AuthOK => authEp.endpoint.settings.patch.?(authEp.endpoint, r), + .AuthOK => authEp.ep.settings.patch.?(authEp.ep, r), .Handled => {}, } } - /// here, the auth_endpoint will be passed in - pub fn options(e: *SimpleEndpoint, r: zap.SimpleRequest) void { + /// OPTIONS: here, the auth_endpoint will be passed in as endpoint. + /// Authenticates OPTIONS requests using the Authenticator. + pub fn options(e: *Endpoint, r: zap.Request) void { const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); switch (authEp.authenticator.authenticateRequest(&r)) { .AuthFailed => { if (e.settings.unauthorized) |unauthorized| { - unauthorized(authEp.endpoint, r); + unauthorized(authEp.ep, r); return; } else { r.setStatus(.unauthorized); @@ -205,7 +274,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { return; } }, - .AuthOK => authEp.endpoint.settings.put.?(authEp.endpoint, r), + .AuthOK => authEp.ep.settings.put.?(authEp.ep, r), .Handled => {}, } } @@ -213,26 +282,44 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type { } pub const EndpointListenerError = error{ + /// Since we use .startsWith to check for matching paths, you cannot use + /// endpoint paths that overlap at the beginning. --> When trying to register + /// an endpoint whose path would shadow an already registered one, you will + /// receive this error. EndpointPathShadowError, }; -// NOTE: We switch on path.startsWith -> so use endpoints with distinctly -// starting names!! -pub const SimpleEndpointListener = struct { +/// The listener with ednpoint support +/// +/// NOTE: It switches on path.startsWith -> so use endpoints with distinctly starting names!! +pub const EndpointListener = struct { listener: Listener, allocator: std.mem.Allocator, const Self = @This(); - /// static struct member endpoints - var endpoints: std.ArrayList(*SimpleEndpoint) = undefined; - var on_request: ?zap.SimpleHttpRequestFn = null; + /// Internal static struct of member endpoints + var endpoints: std.ArrayList(*Endpoint) = undefined; + + /// Internal, static request handler callback. Will be set to the optional, + /// user-defined request callback that only gets called if no endpoints match + /// a request. + var on_request: ?zap.HttpRequestFn = null; + /// Initialize a new endpoint listener. Note, if you pass an `on_request` + /// callback in the provided ListenerSettings, this request callback will be + /// called every time a request arrives that no endpoint matches. pub fn init(a: std.mem.Allocator, l: ListenerSettings) Self { - endpoints = std.ArrayList(*SimpleEndpoint).init(a); + endpoints = std.ArrayList(*Endpoint).init(a); - var ls = l; // take copy of listener settings + // take copy of listener settings before modifying the callback field + var ls = l; + + // override the settings with our internal, actul callback function + // so that "we" will be called on request ls.on_request = onRequest; + + // store the settings-provided request callback for later use on_request = l.on_request; return .{ .listener = Listener.init(ls), @@ -240,16 +327,25 @@ pub const SimpleEndpointListener = struct { }; } + /// De-init the listener and free its resources. + /// Registered endpoints will not be de-initialized automatically; just removed + /// from the internal map. pub fn deinit(self: *Self) void { _ = self; endpoints.deinit(); } + /// Call this to start listening. After this, no more endpoints can be + /// registered. pub fn listen(self: *Self) !void { try self.listener.listen(); } - pub fn addEndpoint(self: *Self, e: *SimpleEndpoint) !void { + /// Register an endpoint with this listener. + /// NOTE: endpoint paths are matched with startsWith -> so use endpoints with distinctly starting names!! + /// If you try to register an endpoint whose path would shadow an already registered one, you will + /// receive an EndpointPathShadowError. + pub fn register(self: *Self, e: *Endpoint) !void { _ = self; for (endpoints.items) |other| { if (std.mem.startsWith( @@ -276,6 +372,7 @@ pub const SimpleEndpointListener = struct { } } } + // if set, call the user-provided default callback if (on_request) |foo| { foo(r); } diff --git a/src/http_auth.zig b/src/http_auth.zig index c883ef7..78e7fb8 100644 --- a/src/http_auth.zig +++ b/src/http_auth.zig @@ -34,7 +34,7 @@ pub fn checkAuthHeader(scheme: AuthScheme, auth_header: []const u8) bool { }; } -pub fn extractAuthHeader(scheme: AuthScheme, r: *const zap.SimpleRequest) ?[]const u8 { +pub fn extractAuthHeader(scheme: AuthScheme, r: *const zap.Request) ?[]const u8 { return switch (scheme) { .Basic => |b| r.getHeader(b.headerFieldStrFio()), .Bearer => |b| r.getHeader(b.headerFieldStrFio()), @@ -180,7 +180,7 @@ pub fn BasicAuth(comptime Lookup: type, comptime kind: BasicAuthStrategy) type { .Token68 => return self.authenticateToken68(auth_header), } } - pub fn authenticateRequest(self: *Self, r: *const zap.SimpleRequest) AuthResult { + pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult { zap.debug("AUTHENTICATE REQUEST\n", .{}); if (extractAuthHeader(.Basic, r)) |auth_header| { zap.debug("Authentication Header found!\n", .{}); @@ -234,7 +234,7 @@ pub const BearerAuthSingle = struct { return if (std.mem.eql(u8, token, self.token)) .AuthOK else .AuthFailed; } - pub fn authenticateRequest(self: *Self, r: *const zap.SimpleRequest) AuthResult { + pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult { if (extractAuthHeader(.Bearer, r)) |auth_header| { return self.authenticate(auth_header); } @@ -292,7 +292,7 @@ pub fn BearerAuthMulti(comptime Lookup: type) type { return if (self.lookup.*.contains(token)) .AuthOK else .AuthFailed; } - pub fn authenticateRequest(self: *Self, r: *const zap.SimpleRequest) AuthResult { + pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult { if (extractAuthHeader(.Bearer, r)) |auth_header| { return self.authenticate(auth_header); } @@ -405,7 +405,7 @@ pub fn UserPassSessionAuth(comptime Lookup: type, comptime lockedPwLookups: bool } /// Check for session token cookie, remove the token from the valid tokens - pub fn logout(self: *Self, r: *const zap.SimpleRequest) void { + pub fn logout(self: *Self, r: *const zap.Request) void { // we erase the list of valid tokens server-side if (r.setCookie(.{ .name = self.settings.cookieName, @@ -439,7 +439,7 @@ pub fn UserPassSessionAuth(comptime Lookup: type, comptime lockedPwLookups: bool } } - fn _internal_authenticateRequest(self: *Self, r: *const zap.SimpleRequest) AuthResult { + fn _internal_authenticateRequest(self: *Self, r: *const zap.Request) AuthResult { // if we're requesting the login page, let the request through if (r.path) |p| { if (std.mem.startsWith(u8, p, self.settings.loginPage)) { @@ -530,7 +530,7 @@ pub fn UserPassSessionAuth(comptime Lookup: type, comptime lockedPwLookups: bool return .AuthFailed; } - pub fn authenticateRequest(self: *Self, r: *const zap.SimpleRequest) AuthResult { + pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult { switch (self._internal_authenticateRequest(r)) { .AuthOK => { // username and pass are ok -> created token, set header, caller can continue @@ -550,7 +550,7 @@ pub fn UserPassSessionAuth(comptime Lookup: type, comptime lockedPwLookups: bool } } - fn redirect(self: *Self, r: *const zap.SimpleRequest) !void { + fn redirect(self: *Self, r: *const zap.Request) !void { try r.redirectTo(self.settings.loginPage, self.settings.redirectCode); } diff --git a/src/middleware.zig b/src/middleware.zig index b435701..7b2dfdb 100644 --- a/src/middleware.zig +++ b/src/middleware.zig @@ -46,7 +46,7 @@ pub fn Handler(comptime ContextType: anytype) type { // will be set allocator: ?std.mem.Allocator = null, - pub const RequestFn = *const fn (*Self, zap.SimpleRequest, *ContextType) bool; + pub const RequestFn = *const fn (*Self, zap.Request, *ContextType) bool; const Self = @This(); pub fn init(on_request: RequestFn, other: ?*Self) Self { @@ -59,7 +59,7 @@ pub fn Handler(comptime ContextType: anytype) type { // example for handling request // which you can use in your components, e.g.: // return self.handler.handleOther(r, context); - pub fn handleOther(self: *Self, r: zap.SimpleRequest, context: *ContextType) bool { + pub fn handleOther(self: *Self, r: zap.Request, context: *ContextType) bool { // in structs embedding a handler, we'd @fieldParentPtr the first // param to get to the real self @@ -80,16 +80,16 @@ pub fn Handler(comptime ContextType: anytype) type { }; } -/// A convenience handler for artibrary zap.SimpleEndpoint +/// A convenience handler for artibrary zap.Endpoint pub fn EndpointHandler(comptime HandlerType: anytype, comptime ContextType: anytype) type { return struct { handler: HandlerType, - endpoint: *zap.SimpleEndpoint, + endpoint: *zap.Endpoint, breakOnFinish: bool, const Self = @This(); - pub fn init(endpoint: *zap.SimpleEndpoint, other: ?*HandlerType, breakOnFinish: bool) Self { + pub fn init(endpoint: *zap.Endpoint, other: ?*HandlerType, breakOnFinish: bool) Self { return .{ .handler = HandlerType.init(onRequest, other), .endpoint = endpoint, @@ -102,7 +102,7 @@ pub fn EndpointHandler(comptime HandlerType: anytype, comptime ContextType: anyt return &self.handler; } - pub fn onRequest(handler: *HandlerType, r: zap.SimpleRequest, context: *ContextType) bool { + pub fn onRequest(handler: *HandlerType, r: zap.Request, context: *ContextType) bool { var self = @fieldParentPtr(Self, "handler", handler); r.setUserContext(context); self.endpoint.onRequest(r); @@ -124,8 +124,8 @@ pub const RequestAllocatorFn = *const fn () std.mem.Allocator; pub fn Listener(comptime ContextType: anytype) type { return struct { - listener: zap.SimpleHttpListener = undefined, - settings: zap.SimpleHttpListenerSettings, + listener: zap.HttpListener = undefined, + settings: zap.HttpListenerSettings, // static initial handler var handler: ?*Handler(ContextType) = undefined; @@ -136,7 +136,7 @@ pub fn Listener(comptime ContextType: anytype) type { /// initialize the middleware handler /// the passed in settings must have on_request set to null - pub fn init(settings: zap.SimpleHttpListenerSettings, initial_handler: *Handler(ContextType), request_alloc: ?RequestAllocatorFn) Error!Self { + pub fn init(settings: zap.HttpListenerSettings, initial_handler: *Handler(ContextType), request_alloc: ?RequestAllocatorFn) Error!Self { // override on_request with ourselves if (settings.on_request != null) { return Error.InitOnRequestIsNotNull; @@ -148,7 +148,7 @@ pub fn Listener(comptime ContextType: anytype) type { .settings = settings, }; ret.settings.on_request = onRequest; - ret.listener = zap.SimpleHttpListener.init(ret.settings); + ret.listener = zap.HttpListener.init(ret.settings); handler = initial_handler; return ret; } @@ -161,7 +161,7 @@ pub fn Listener(comptime ContextType: anytype) type { // but it's actually used obviously. Create your own listener if you // want different behavior. // Didn't want to make this a callback - pub fn onRequest(r: zap.SimpleRequest) void { + pub fn onRequest(r: zap.Request) void { // we are the 1st handler in the chain, so we create a context var context: ContextType = .{}; diff --git a/src/tests/test_auth.zig b/src/tests/test_auth.zig index 4055695..e84beab 100644 --- a/src/tests/test_auth.zig +++ b/src/tests/test_auth.zig @@ -106,7 +106,7 @@ const HTTP_RESPONSE: []const u8 = ; var received_response: []const u8 = "null"; -fn endpoint_http_get(e: *Endpoints.SimpleEndpoint, r: zap.SimpleRequest) void { +fn endpoint_http_get(e: *Endpoints.Endpoint, r: zap.Request) void { _ = e; r.sendBody(HTTP_RESPONSE) catch return; received_response = HTTP_RESPONSE; @@ -114,7 +114,7 @@ fn endpoint_http_get(e: *Endpoints.SimpleEndpoint, r: zap.SimpleRequest) void { zap.fio_stop(); } -fn endpoint_http_unauthorized(e: *Endpoints.SimpleEndpoint, r: zap.SimpleRequest) void { +fn endpoint_http_unauthorized(e: *Endpoints.Endpoint, r: zap.Request) void { _ = e; r.setStatus(.unauthorized); r.sendBody("UNAUTHORIZED ACCESS") catch return; @@ -181,7 +181,7 @@ test "BearerAuthSingle authenticateRequest OK" { const token = "ABCDEFG"; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -194,7 +194,7 @@ test "BearerAuthSingle authenticateRequest OK" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -209,7 +209,7 @@ test "BearerAuthSingle authenticateRequest OK" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("\n\n*******************************************\n", .{}); @@ -234,7 +234,7 @@ test "BearerAuthSingle authenticateRequest test-unauthorized" { const token = "ABCDEFG"; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -247,7 +247,7 @@ test "BearerAuthSingle authenticateRequest test-unauthorized" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -268,7 +268,7 @@ test "BearerAuthSingle authenticateRequest test-unauthorized" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); @@ -291,7 +291,7 @@ test "BearerAuthMulti authenticateRequest OK" { const token = "ABCDEFG"; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -304,7 +304,7 @@ test "BearerAuthMulti authenticateRequest OK" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -319,7 +319,7 @@ test "BearerAuthMulti authenticateRequest OK" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); @@ -342,7 +342,7 @@ test "BearerAuthMulti authenticateRequest test-unauthorized" { const token = "invalid"; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -355,7 +355,7 @@ test "BearerAuthMulti authenticateRequest test-unauthorized" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -370,7 +370,7 @@ test "BearerAuthMulti authenticateRequest test-unauthorized" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); @@ -393,7 +393,7 @@ test "BasicAuth Token68 authenticateRequest" { const token = "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -406,7 +406,7 @@ test "BasicAuth Token68 authenticateRequest" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -426,7 +426,7 @@ test "BasicAuth Token68 authenticateRequest" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); @@ -449,7 +449,7 @@ test "BasicAuth Token68 authenticateRequest test-unauthorized" { const token = "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -462,7 +462,7 @@ test "BasicAuth Token68 authenticateRequest test-unauthorized" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -482,7 +482,7 @@ test "BasicAuth Token68 authenticateRequest test-unauthorized" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); @@ -504,7 +504,7 @@ test "BasicAuth UserPass authenticateRequest" { const a = std.testing.allocator; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -517,7 +517,7 @@ test "BasicAuth UserPass authenticateRequest" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -548,7 +548,7 @@ test "BasicAuth UserPass authenticateRequest" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); @@ -570,7 +570,7 @@ test "BasicAuth UserPass authenticateRequest test-unauthorized" { const a = std.testing.allocator; // setup listener - var listener = zap.SimpleEndpointListener.init( + var listener = zap.EndpointListener.init( a, .{ .port = 3000, @@ -583,7 +583,7 @@ test "BasicAuth UserPass authenticateRequest test-unauthorized" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ + var ep = Endpoints.Endpoint.init(.{ .path = "/test", .get = endpoint_http_get, .unauthorized = endpoint_http_unauthorized, @@ -615,7 +615,7 @@ test "BasicAuth UserPass authenticateRequest test-unauthorized" { const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); - try listener.addEndpoint(auth_ep.getEndpoint()); + try listener.register(auth_ep.endpoint()); listener.listen() catch {}; // std.debug.print("Waiting for the following:\n", .{}); diff --git a/src/tests/test_http_params.zig b/src/tests/test_http_params.zig index 00b23bc..dbc3ad1 100644 --- a/src/tests/test_http_params.zig +++ b/src/tests/test_http_params.zig @@ -34,7 +34,7 @@ test "http parameters" { var params: ?zap.HttpParamKVList = null; var paramOneStr: ?zap.FreeOrNot = null; - pub fn on_request(r: zap.SimpleRequest) void { + pub fn on_request(r: zap.Request) void { ran = true; r.parseQuery(); param_count = r.getParamCount(); @@ -55,7 +55,7 @@ test "http parameters" { Handler.alloc = allocator; // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3001, .on_request = Handler.on_request, diff --git a/src/tests/test_sendfile.zig b/src/tests/test_sendfile.zig index 5b0f5c4..2725f9d 100644 --- a/src/tests/test_sendfile.zig +++ b/src/tests/test_sendfile.zig @@ -28,7 +28,7 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void { fn makeRequestThread(a: std.mem.Allocator, url: []const u8) !std.Thread { return try std.Thread.spawn(.{}, makeRequest, .{ a, url }); } -pub fn on_request(r: zap.SimpleRequest) void { +pub fn on_request(r: zap.Request) void { r.sendFile("src/tests/testfile.txt") catch unreachable; } @@ -36,7 +36,7 @@ test "send file" { var allocator = std.testing.allocator; // setup listener - var listener = zap.SimpleHttpListener.init( + var listener = zap.HttpListener.init( .{ .port = 3002, .on_request = on_request, diff --git a/src/zap.zig b/src/zap.zig index 1f5bc02..49dc531 100644 --- a/src/zap.zig +++ b/src/zap.zig @@ -76,7 +76,7 @@ pub const ContentType = enum { JSON, }; -pub const SimpleRequest = struct { +pub const Request = struct { path: ?[]const u8, query: ?[]const u8, body: ?[]const u8, @@ -90,7 +90,7 @@ pub const SimpleRequest = struct { /// NEVER touch this field!!!! /// use markAsFinished() and isFinished() instead /// this is a hack: the listener will put a pointer to this into the udata - /// field of `h`. So copies of the SimpleRequest will all have way to the + /// field of `h`. So copies of the Request will all have way to the /// same instance of this field. _is_finished_request_global: bool, /// NEVER touch this field!!!! @@ -156,7 +156,7 @@ pub const SimpleRequest = struct { *anyopaque, @ptrFromInt(@intFromPtr(body.ptr)), ), body.len); - debug("SimpleRequest.sendBody(): ret = {}\n", .{ret}); + debug("Request.sendBody(): ret = {}\n", .{ret}); if (ret == -1) return error.HttpSendBody; self.markAsFinished(true); } @@ -744,25 +744,26 @@ pub const CookieArgs = struct { http_only: bool = true, }; -pub const HttpRequestFn = *const fn (r: [*c]fio.http_s) callconv(.C) void; -pub const SimpleHttpRequestFn = *const fn (SimpleRequest) void; +pub const FioHttpRequestFn = *const fn (r: [*c]fio.http_s) callconv(.C) void; + +pub const HttpRequestFn = *const fn (Request) void; /// websocket connection upgrade /// fn(request, targetstring) -pub const SimpleHttpUpgradeFn = *const fn (r: SimpleRequest, target_protocol: []const u8) void; +pub const HttpUpgradeFn = *const fn (r: Request, target_protocol: []const u8) void; /// http finish, called when zap finishes. You get your udata back in the /// struct. -pub const SimpleHttpFinishSettings = [*c]fio.struct_http_settings_s; -pub const SimpleHttpFinishFn = *const fn (SimpleHttpFinishSettings) void; +pub const HttpFinishSettings = [*c]fio.struct_http_settings_s; +pub const HttpFinishFn = *const fn (HttpFinishSettings) void; -pub const SimpleHttpListenerSettings = struct { +pub const HttpListenerSettings = struct { port: usize, interface: [*c]const u8 = null, - on_request: ?SimpleHttpRequestFn, - on_response: ?SimpleHttpRequestFn = null, - on_upgrade: ?SimpleHttpUpgradeFn = null, - on_finish: ?SimpleHttpFinishFn = null, + on_request: ?HttpRequestFn, + on_response: ?HttpRequestFn = null, + on_upgrade: ?HttpUpgradeFn = null, + on_finish: ?HttpFinishFn = null, // provide any pointer in there for "user data". it will be passed pack in // on_finish()'s copy of the struct_http_settings_s udata: ?*anyopaque = null, @@ -776,13 +777,13 @@ pub const SimpleHttpListenerSettings = struct { tls: ?Tls = null, }; -pub const SimpleHttpListener = struct { - settings: SimpleHttpListenerSettings, +pub const HttpListener = struct { + settings: HttpListenerSettings, const Self = @This(); - var the_one_and_only_listener: ?*SimpleHttpListener = null; + var the_one_and_only_listener: ?*HttpListener = null; - pub fn init(settings: SimpleHttpListenerSettings) Self { + pub fn init(settings: HttpListenerSettings) Self { std.debug.assert(settings.on_request != null); return .{ .settings = settings, @@ -792,10 +793,10 @@ pub const SimpleHttpListener = struct { // on_upgrade: ?*const fn ([*c]fio.http_s, [*c]u8, usize) callconv(.C) void = null, // on_finish: ?*const fn ([*c]fio.struct_http_settings_s) callconv(.C) void = null, - // we could make it dynamic by passing a SimpleHttpListener via udata + // we could make it dynamic by passing a HttpListener via udata pub fn theOneAndOnlyRequestCallBack(r: [*c]fio.http_s) callconv(.C) void { if (the_one_and_only_listener) |l| { - var req: SimpleRequest = .{ + var req: Request = .{ .path = util.fio2str(r.*.path), .query = util.fio2str(r.*.query), .body = util.fio2str(r.*.body), @@ -806,7 +807,7 @@ pub const SimpleHttpListener = struct { }; req._is_finished = &req._is_finished_request_global; - var user_context: SimpleRequest.UserContext = .{}; + var user_context: Request.UserContext = .{}; req._user_context = &user_context; req.markAsFinished(false); @@ -820,7 +821,7 @@ pub const SimpleHttpListener = struct { pub fn theOneAndOnlyResponseCallBack(r: [*c]fio.http_s) callconv(.C) void { if (the_one_and_only_listener) |l| { - var req: SimpleRequest = .{ + var req: Request = .{ .path = util.fio2str(r.*.path), .query = util.fio2str(r.*.query), .body = util.fio2str(r.*.body), @@ -831,7 +832,7 @@ pub const SimpleHttpListener = struct { }; req._is_finished = &req._is_finished_request_global; - var user_context: SimpleRequest.UserContext = .{}; + var user_context: Request.UserContext = .{}; req._user_context = &user_context; l.settings.on_response.?(req); @@ -840,7 +841,7 @@ pub const SimpleHttpListener = struct { pub fn theOneAndOnlyUpgradeCallBack(r: [*c]fio.http_s, target: [*c]u8, target_len: usize) callconv(.C) void { if (the_one_and_only_listener) |l| { - var req: SimpleRequest = .{ + var req: Request = .{ .path = util.fio2str(r.*.path), .query = util.fio2str(r.*.query), .body = util.fio2str(r.*.body), @@ -852,7 +853,7 @@ pub const SimpleHttpListener = struct { var zigtarget: []u8 = target[0..target_len]; req._is_finished = &req._is_finished_request_global; - var user_context: SimpleRequest.UserContext = .{}; + var user_context: Request.UserContext = .{}; req._user_context = &user_context; l.settings.on_upgrade.?(req, zigtarget); @@ -870,7 +871,7 @@ pub const SimpleHttpListener = struct { var pfolder_len: usize = 0; if (self.settings.public_folder) |pf| { - debug("SimpleHttpListener.listen(): public folder is {s}\n", .{pf}); + debug("HttpListener.listen(): public folder is {s}\n", .{pf}); pfolder_len = pf.len; pfolder = pf.ptr; } @@ -916,7 +917,7 @@ pub const SimpleHttpListener = struct { // set ourselves up to handle requests: // TODO: do we mind the race condition? - // the SimpleHttpRequestFn will check if this is null and not process + // the HttpRequestFn will check if this is null and not process // the request if it isn't set. hence, if started under full load, the // first request(s) might not be serviced, as long as it takes from // fio.http_listen() to here @@ -928,10 +929,10 @@ pub const SimpleHttpListener = struct { // lower level listening // pub const ListenSettings = struct { - on_request: ?*const fn ([*c]fio.http_s) callconv(.C) void = null, - on_upgrade: ?*const fn ([*c]fio.http_s, [*c]u8, usize) callconv(.C) void = null, - on_response: ?*const fn ([*c]fio.http_s) callconv(.C) void = null, - on_finish: ?*const fn ([*c]fio.struct_http_settings_s) callconv(.C) void = null, + on_request: ?FioHttpRequestFn = null, + on_upgrade: ?FioHttpRequestFn = null, + on_response: ?FioHttpRequestFn = null, + on_finish: ?FioHttpRequestFn = null, public_folder: ?[]const u8 = null, max_header_size: usize = 32 * 1024, max_body_size: usize = 50 * 1024 * 1024, diff --git a/wrk/zig/main.zig b/wrk/zig/main.zig index 555cf71..20fa3f3 100644 --- a/wrk/zig/main.zig +++ b/wrk/zig/main.zig @@ -1,12 +1,12 @@ const std = @import("std"); const zap = @import("zap"); -fn on_request_minimal(r: zap.SimpleRequest) void { +fn on_request_minimal(r: zap.Request) void { r.sendBody("Hello from ZAP!!!") catch return; } pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ + var listener = zap.HttpListener.init(.{ .port = 3000, .on_request = on_request_minimal, .log = false,