1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-20 23:24:09 +00:00

endpoints, auth endpoints, middleware endpoints: eliminate need for empty stubs

This commit is contained in:
renerocksai 2025-07-23 20:23:49 +02:00
parent baaa71d0e0
commit dabd0637f9
No known key found for this signature in database
9 changed files with 59 additions and 80 deletions

View file

@ -13,11 +13,3 @@ pub fn get(_: *ErrorEndpoint, _: zap.Request) !void {
// --> this error will be shown in the browser, with a nice error trace
return error.@"Oh-no!";
}
// unused:
pub fn post(_: *ErrorEndpoint, _: zap.Request) !void {}
pub fn put(_: *ErrorEndpoint, _: zap.Request) !void {}
pub fn delete(_: *ErrorEndpoint, _: zap.Request) !void {}
pub fn patch(_: *ErrorEndpoint, _: zap.Request) !void {}
pub fn options(_: *ErrorEndpoint, _: zap.Request) !void {}
pub fn head(_: *ErrorEndpoint, _: zap.Request) !void {}

View file

@ -17,10 +17,3 @@ pub fn init(path: []const u8) StopEndpoint {
pub fn get(_: *StopEndpoint, _: zap.Request) !void {
zap.stop();
}
pub fn post(_: *StopEndpoint, _: zap.Request) !void {}
pub fn put(_: *StopEndpoint, _: zap.Request) !void {}
pub fn delete(_: *StopEndpoint, _: zap.Request) !void {}
pub fn patch(_: *StopEndpoint, _: zap.Request) !void {}
pub fn options(_: *StopEndpoint, _: zap.Request) !void {}
pub fn head(_: *StopEndpoint, _: zap.Request) !void {}

View file

@ -43,7 +43,8 @@ fn userIdFromPath(self: *UserWeb, path: []const u8) ?usize {
return null;
}
pub fn put(_: *UserWeb, _: zap.Request) !void {}
// not implemented
// pub fn put(_: *UserWeb, _: zap.Request) !void {}
pub fn get(self: *UserWeb, r: zap.Request) !void {
if (r.path) |path| {

View file

@ -31,14 +31,6 @@ const Endpoint = struct {
r.setStatus(.unauthorized);
r.sendBody("UNAUTHORIZED ACCESS") catch return;
}
// not implemented, don't care
pub fn post(_: *Endpoint, _: zap.Request) !void {}
pub fn put(_: *Endpoint, _: zap.Request) !void {}
pub fn delete(_: *Endpoint, _: zap.Request) !void {}
pub fn patch(_: *Endpoint, _: zap.Request) !void {}
pub fn options(_: *Endpoint, _: zap.Request) !void {}
pub fn head(_: *Endpoint, _: zap.Request) !void {}
};
pub fn main() !void {

View file

@ -152,13 +152,6 @@ const HtmlEndpoint = struct {
};
}
pub fn post(_: *HtmlEndpoint, _: zap.Request) !void {}
pub fn put(_: *HtmlEndpoint, _: zap.Request) !void {}
pub fn delete(_: *HtmlEndpoint, _: zap.Request) !void {}
pub fn patch(_: *HtmlEndpoint, _: zap.Request) !void {}
pub fn options(_: *HtmlEndpoint, _: zap.Request) !void {}
pub fn head(_: *HtmlEndpoint, _: zap.Request) !void {}
pub fn get(_: *HtmlEndpoint, r: zap.Request) !void {
var buf: [1024]u8 = undefined;
var userFound: bool = false;

View file

@ -5,7 +5,11 @@
//! Pass an instance of an Endpoint struct to zap.Endpoint.Listener.register()
//! function to register with the listener.
//!
//! **NOTE**: Endpoints must implement the following "interface":
//! **NOTE**: Endpoints can implement the following "interface":
//!
//! Any method handler that's not implemented will be handled automatically:
//! - zap will log it
//! - a response with status code 405 (method not allowed) is sent to the client
//!
//! ```zig
//! /// The http request path / slug of the endpoint
@ -13,6 +17,7 @@
//! error_strategy: zap.Endpoint.ErrorStrategy,
//!
//! /// Handlers by request method:
//! /// implement any of the following
//! pub fn get(_: *Self, _: zap.Request) !void {}
//! pub fn post(_: *Self, _: zap.Request) !void {}
//! pub fn put(_: *Self, _: zap.Request) !void {}
@ -44,13 +49,6 @@
//! pub fn get(_: *StopEndpoint, _: zap.Request) !void {
//! zap.stop();
//! }
//!
//! pub fn post(_: *StopEndpoint, _: zap.Request) !void {}
//! pub fn put(_: *StopEndpoint, _: zap.Request) !void {}
//! pub fn delete(_: *StopEndpoint, _: zap.Request) !void {}
//! pub fn patch(_: *StopEndpoint, _: zap.Request) !void {}
//! pub fn options(_: *StopEndpoint, _: zap.Request) !void {}
//! pub fn head(_: *StopEndpoint, _: zap.Request) !void {}
//! };
//! ```
@ -154,10 +152,25 @@ pub fn checkEndpointType(T: type) void {
@compileError("Expected return type of method `" ++ @typeName(T) ++ "." ++ method ++ "` to be !void, got: !" ++ @typeName(ret_info.error_union.payload));
}
} else {
@compileError(@typeName(T) ++ " has no method named `" ++ method ++ "`");
// it is ok not to implement a method handler
// pass
}
}
}
// This can be resolved at comptime so *perhaps it does affect optimiazation
pub fn callHandlerIfExist(comptime fn_name: []const u8, e: anytype, r: Request) anyerror!void {
const EndPointType = @TypeOf(e.*);
if (@hasDecl(EndPointType, fn_name)) {
return @field(EndPointType, fn_name)(e, r);
}
zap.log.debug(
"Unhandled `{s}` {s} request ({s} not implemented in {s})",
.{ r.method orelse "<unknown>", r.path orelse "", fn_name, @typeName(EndPointType) },
);
r.setStatus(.method_not_allowed);
try r.sendBody("405 - method not allowed\r\n");
return;
}
pub const Binder = struct {
pub const Interface = struct {
@ -189,13 +202,13 @@ pub const Binder = struct {
pub fn onRequest(self: *Bound, r: zap.Request) !void {
const ret = switch (r.methodAsEnum()) {
.GET => self.endpoint.*.get(r),
.POST => self.endpoint.*.post(r),
.PUT => self.endpoint.*.put(r),
.DELETE => self.endpoint.*.delete(r),
.PATCH => self.endpoint.*.patch(r),
.OPTIONS => self.endpoint.*.options(r),
.HEAD => self.endpoint.*.head(r),
.GET => callHandlerIfExist("get", self.endpoint, r),
.POST => callHandlerIfExist("post", self.endpoint, r),
.PUT => callHandlerIfExist("put", self.endpoint, r),
.DELETE => callHandlerIfExist("delete", self.endpoint, r),
.PATCH => callHandlerIfExist("patch", self.endpoint, r),
.OPTIONS => callHandlerIfExist("options", self.endpoint, r),
.HEAD => callHandlerIfExist("head", self.endpoint, r),
else => error.UnsupportedHtmlRequestMethod,
};
if (ret) {
@ -249,8 +262,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates GET requests using the Authenticator.
pub fn get(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.get(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("get", self.ep, r),
.Handled => {},
};
}
@ -258,8 +271,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates POST requests using the Authenticator.
pub fn post(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.post(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("post", self.ep, r),
.Handled => {},
};
}
@ -267,8 +280,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates PUT requests using the Authenticator.
pub fn put(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.put(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("put", self.ep, r),
.Handled => {},
};
}
@ -276,8 +289,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates DELETE requests using the Authenticator.
pub fn delete(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.delete(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("delete", self.ep, r),
.Handled => {},
};
}
@ -285,8 +298,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates PATCH requests using the Authenticator.
pub fn patch(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.patch(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("patch", self.ep, r),
.Handled => {},
};
}
@ -294,8 +307,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates OPTIONS requests using the Authenticator.
pub fn options(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.put(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("options", self.ep, r),
.Handled => {},
};
}
@ -303,8 +316,8 @@ pub fn Authenticating(EndpointType: type, Authenticator: type) type {
/// Authenticates HEAD requests using the Authenticator.
pub fn head(self: *AuthenticatingEndpoint, r: zap.Request) anyerror!void {
try switch (self.authenticator.authenticateRequest(&r)) {
.AuthFailed => return self.ep.*.unauthorized(r),
.AuthOK => self.ep.*.head(r),
.AuthFailed => callHandlerIfExist("unauthorized", self.ep, r),
.AuthOK => callHandlerIfExist("head", self.ep, r),
.Handled => {},
};
}

View file

@ -1,5 +1,6 @@
const std = @import("std");
const zap = @import("zap.zig");
const callHandlerIfExist = @import("endpoint.zig").callHandlerIfExist;
/// Your middleware components need to contain a handler.
///
@ -102,16 +103,16 @@ pub fn EndpointHandler(comptime HandlerType: anytype, comptime EndpointType: any
if (!self.options.checkPath or
std.mem.startsWith(u8, r.path orelse "", self.endpoint.path))
{
switch (r.methodAsEnum()) {
.GET => try self.endpoint.*.get(r),
.POST => try self.endpoint.*.post(r),
.PUT => try self.endpoint.*.put(r),
.DELETE => try self.endpoint.*.delete(r),
.PATCH => try self.endpoint.*.patch(r),
.OPTIONS => try self.endpoint.*.options(r),
.HEAD => try self.endpoint.*.head(r),
try switch (r.methodAsEnum()) {
.GET => callHandlerIfExist("get", self.endpoint, r),
.POST => callHandlerIfExist("post", self.endpoint, r),
.PUT => callHandlerIfExist("put", self.endpoint, r),
.DELETE => callHandlerIfExist("delete", self.endpoint, r),
.PATCH => callHandlerIfExist("patch", self.endpoint, r),
.OPTIONS => callHandlerIfExist("options", self.endpoint, r),
.HEAD => callHandlerIfExist("head", self.endpoint, r),
else => {},
}
};
}
// if the request was handled by the endpoint, we may break the chain here

View file

@ -165,12 +165,6 @@ pub const Endpoint = struct {
std.time.sleep(1 * std.time.ns_per_s);
zap.stop();
}
pub fn post(_: *Endpoint, _: zap.Request) !void {}
pub fn put(_: *Endpoint, _: zap.Request) !void {}
pub fn delete(_: *Endpoint, _: zap.Request) !void {}
pub fn patch(_: *Endpoint, _: zap.Request) !void {}
pub fn options(_: *Endpoint, _: zap.Request) !void {}
pub fn head(_: *Endpoint, _: zap.Request) !void {}
};
//
// end of http client code