mirror of
https://github.com/zigzap/zap.git
synced 2025-10-20 07:04:08 +00:00
API cleanup #1
-------------- - EndpointListener.register() // was: addEndpoint - no more Simple - getEndpoint -> endpoint()
This commit is contained in:
parent
5a284fc96d
commit
3d651229f8
32 changed files with 353 additions and 252 deletions
|
@ -113,9 +113,9 @@ port and docs dir: `zig build docserver && zig-out/bin/docserver --port=8989
|
|||
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
|
||||
|
@ -376,7 +376,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});
|
||||
}
|
||||
|
@ -388,7 +388,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,
|
||||
|
|
|
@ -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(
|
||||
\\ <html><body>
|
||||
|
@ -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(
|
||||
\\ <html><body>
|
||||
|
@ -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(
|
||||
\\ <html><body>
|
||||
|
@ -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(
|
||||
\\ <html><body>
|
||||
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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| {
|
||||
const 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| {
|
||||
const 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;
|
|
@ -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(
|
||||
|
|
|
@ -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("<html><body><h1>Hello from ZAP!!!</h1></body></html>") catch return;
|
||||
}
|
||||
|
||||
fn on_request_minimal(r: zap.SimpleRequest) void {
|
||||
fn on_request_minimal(r: zap.Request) void {
|
||||
r.sendBody("<html><body><h1>Hello from ZAP!!!</h1></body></html>") 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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
const 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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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("<html><body><h1>Hello from ZAP!!!</h1></body></html>") catch return;
|
||||
}
|
||||
|
||||
fn on_request_minimal(r: zap.SimpleRequest) void {
|
||||
fn on_request_minimal(r: zap.Request) void {
|
||||
r.sendBody("<html><body><h1>Hello from ZAP!!!</h1></body></html>") 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,
|
||||
|
|
|
@ -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
|
||||
const 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
|
||||
const 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
|
||||
const self = @fieldParentPtr(Self, "handler", handler);
|
||||
|
|
|
@ -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
|
||||
const 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
|
||||
const 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 {
|
||||
const 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.
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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("<html><body><h1>Hello from STATIC ZAP!</h1></body></html>") 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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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("<html><body><h1>404 - File not found</h1></body></html>") 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",
|
||||
|
|
|
@ -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(
|
||||
\\ <html><body>
|
||||
|
@ -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.
|
||||
|
@ -124,7 +124,7 @@ pub fn main() !void {
|
|||
// to detect leaks
|
||||
{
|
||||
const allocator = gpa.allocator();
|
||||
var listener = zap.SimpleHttpListener.init(.{
|
||||
var listener = zap.HttpListener.init(.{
|
||||
.port = 3000,
|
||||
.on_request = on_request,
|
||||
.log = true,
|
||||
|
|
|
@ -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(
|
||||
\\ <html><body>
|
||||
|
@ -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,
|
||||
|
|
205
src/endpoint.zig
205
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = .{};
|
||||
|
||||
|
|
|
@ -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", .{});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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" {
|
|||
const allocator = std.testing.allocator;
|
||||
|
||||
// setup listener
|
||||
var listener = zap.SimpleHttpListener.init(
|
||||
var listener = zap.HttpListener.init(
|
||||
.{
|
||||
.port = 3002,
|
||||
.on_request = on_request,
|
||||
|
|
61
src/zap.zig
61
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 {
|
|||
const 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,
|
||||
|
|
|
@ -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 {
|
||||
r.setStatus(.not_found);
|
||||
r.sendBody("<html><body><h1>404 - File not found</h1></body></html>") catch return;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ pub fn main() !void {
|
|||
}
|
||||
}
|
||||
|
||||
var listener = zap.SimpleHttpListener.init(.{
|
||||
var listener = zap.HttpListener.init(.{
|
||||
.port = port,
|
||||
.on_request = on_request,
|
||||
.public_folder = docs_dir,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue