mirror of
https://github.com/zigzap/zap.git
synced 2025-10-20 15:14:08 +00:00
Merge pull request #171 from Tesseract22/master
Provide defaults to unimplemented methods in endpoints for App style api.
This commit is contained in:
commit
29d339892e
4 changed files with 46 additions and 61 deletions
|
@ -58,14 +58,6 @@ const MyEndpoint = struct {
|
|||
);
|
||||
try r.sendBody(response);
|
||||
}
|
||||
|
||||
// not implemented, don't care
|
||||
pub fn post(_: *MyEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn put(_: *MyEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn delete(_: *MyEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn patch(_: *MyEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn options(_: *MyEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn head(_: *MyEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
|
@ -83,8 +75,8 @@ pub fn main() !void {
|
|||
// App is the type
|
||||
// app is the instance
|
||||
const App = zap.App.Create(MyContext);
|
||||
var app = try App.init(allocator, &my_context, .{});
|
||||
defer app.deinit();
|
||||
try App.init(allocator, &my_context, .{});
|
||||
defer App.deinit();
|
||||
|
||||
// create mini endpoint
|
||||
var ep: MyEndpoint = .{
|
||||
|
@ -101,10 +93,10 @@ pub fn main() !void {
|
|||
var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator);
|
||||
|
||||
// make the authenticating endpoint known to the app
|
||||
try app.register(&auth_ep);
|
||||
try App.register(&auth_ep);
|
||||
|
||||
// listen
|
||||
try app.listen(.{
|
||||
try App.listen(.{
|
||||
.interface = "0.0.0.0",
|
||||
.port = 3000,
|
||||
});
|
||||
|
|
|
@ -59,15 +59,7 @@ const SimpleEndpoint = struct {
|
|||
try r.sendBody(response_text);
|
||||
std.time.sleep(std.time.ns_per_ms * 300);
|
||||
}
|
||||
|
||||
// empty stubs for all other request methods
|
||||
pub fn post(_: *SimpleEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn put(_: *SimpleEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn delete(_: *SimpleEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn patch(_: *SimpleEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn options(_: *SimpleEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn head(_: *SimpleEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
};
|
||||
};
|
||||
|
||||
const StopEndpoint = struct {
|
||||
path: []const u8,
|
||||
|
@ -82,12 +74,6 @@ const StopEndpoint = struct {
|
|||
, .{context.*.db_connection});
|
||||
zap.stop();
|
||||
}
|
||||
|
||||
pub fn post(_: *StopEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn put(_: *StopEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn delete(_: *StopEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn patch(_: *StopEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
pub fn options(_: *StopEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
|
@ -104,19 +90,19 @@ pub fn main() !void {
|
|||
|
||||
// create an App instance
|
||||
const App = zap.App.Create(MyContext);
|
||||
var app = try App.init(allocator, &my_context, .{});
|
||||
defer app.deinit();
|
||||
try App.init(allocator, &my_context, .{});
|
||||
defer App.deinit();
|
||||
|
||||
// create the endpoints
|
||||
var my_endpoint = SimpleEndpoint.init("/test", "some endpoint specific data");
|
||||
var stop_endpoint: StopEndpoint = .{ .path = "/stop" };
|
||||
//
|
||||
// register the endpoints with the app
|
||||
try app.register(&my_endpoint);
|
||||
try app.register(&stop_endpoint);
|
||||
// register the endpoints with the App
|
||||
try App.register(&my_endpoint);
|
||||
try App.register(&stop_endpoint);
|
||||
|
||||
// listen on the network
|
||||
try app.listen(.{
|
||||
try App.listen(.{
|
||||
.interface = "0.0.0.0",
|
||||
.port = 3000,
|
||||
});
|
||||
|
|
|
@ -86,24 +86,24 @@ pub fn main() !void {
|
|||
defer std.debug.print("\n\nLeaks detected: {}\n\n", .{gpa.deinit() != .ok});
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
// create an app context
|
||||
// create an App context
|
||||
var my_context: MyContext = .{ .db_connection = "db connection established!" };
|
||||
|
||||
// create an App instance
|
||||
const App = zap.App.Create(MyContext);
|
||||
var app = try App.init(allocator, &my_context, .{});
|
||||
defer app.deinit();
|
||||
try App.init(allocator, &my_context, .{});
|
||||
defer App.deinit();
|
||||
|
||||
// create the endpoints
|
||||
var my_endpoint = ErrorEndpoint.init("/error", "some endpoint specific data");
|
||||
var stop_endpoint: StopEndpoint = .{ .path = "/stop" };
|
||||
//
|
||||
// register the endpoints with the app
|
||||
try app.register(&my_endpoint);
|
||||
try app.register(&stop_endpoint);
|
||||
// register the endpoints with the App
|
||||
try App.register(&my_endpoint);
|
||||
try App.register(&stop_endpoint);
|
||||
|
||||
// listen on the network
|
||||
try app.listen(.{
|
||||
try App.listen(.{
|
||||
.interface = "0.0.0.0",
|
||||
.port = 3000,
|
||||
});
|
||||
|
|
49
src/App.zig
49
src/App.zig
|
@ -110,14 +110,15 @@ pub fn Create(
|
|||
}
|
||||
|
||||
pub fn onRequest(self: *Bound, arena: Allocator, app_context: *Context, r: Request) !void {
|
||||
// TODO: simplitfy this with @tagName?
|
||||
const ret = switch (r.methodAsEnum()) {
|
||||
.GET => self.endpoint.*.get(arena, app_context, r),
|
||||
.POST => self.endpoint.*.post(arena, app_context, r),
|
||||
.PUT => self.endpoint.*.put(arena, app_context, r),
|
||||
.DELETE => self.endpoint.*.delete(arena, app_context, r),
|
||||
.PATCH => self.endpoint.*.patch(arena, app_context, r),
|
||||
.OPTIONS => self.endpoint.*.options(arena, app_context, r),
|
||||
.HEAD => self.endpoint.*.head(arena, app_context, r),
|
||||
.GET => callHandlerIfExist("get", self.endpoint, arena, app_context, r),
|
||||
.POST => callHandlerIfExist("post", self.endpoint, arena, app_context, r),
|
||||
.PUT => callHandlerIfExist("put", self.endpoint, arena, app_context, r),
|
||||
.DELETE => callHandlerIfExist("delete", self.endpoint, arena, app_context, r),
|
||||
.PATCH => callHandlerIfExist("patch", self.endpoint, arena, app_context, r),
|
||||
.OPTIONS => callHandlerIfExist("options", self.endpoint, arena, app_context, r),
|
||||
.HEAD => callHandlerIfExist("head", self.endpoint, arena, app_context, r),
|
||||
else => error.UnsupportedHtmlRequestMethod,
|
||||
};
|
||||
if (ret) {
|
||||
|
@ -227,8 +228,6 @@ pub fn Create(
|
|||
if (ret_info.error_union.payload != 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 ++ "`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +257,7 @@ pub fn Create(
|
|||
pub fn get(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.get(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("get", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -267,7 +266,7 @@ pub fn Create(
|
|||
pub fn post(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.post(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("post", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -276,7 +275,7 @@ pub fn Create(
|
|||
pub fn put(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: zap.Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.put(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("put", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -285,7 +284,7 @@ pub fn Create(
|
|||
pub fn delete(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: zap.Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.delete(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("delete", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -294,7 +293,7 @@ pub fn Create(
|
|||
pub fn patch(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: zap.Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.patch(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("patch", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -303,7 +302,7 @@ pub fn Create(
|
|||
pub fn options(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: zap.Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.put(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("options", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -312,7 +311,7 @@ pub fn Create(
|
|||
pub fn head(self: *AuthenticatingEndpoint, arena: Allocator, context: *Context, request: zap.Request) anyerror!void {
|
||||
try switch (self.authenticator.authenticateRequest(&request)) {
|
||||
.AuthFailed => return self.ep.*.unauthorized(arena, context, request),
|
||||
.AuthOK => self.ep.*.head(arena, context, request),
|
||||
.AuthOK => callHandlerIfExist("head", self.ep, arena, context, request),
|
||||
.Handled => {},
|
||||
};
|
||||
}
|
||||
|
@ -332,7 +331,7 @@ pub fn Create(
|
|||
tls: ?zap.Tls = null,
|
||||
};
|
||||
|
||||
pub fn init(gpa_: Allocator, context_: *Context, opts_: AppOpts) !App {
|
||||
pub fn init(gpa_: Allocator, context_: *Context, opts_: AppOpts) !void {
|
||||
if (_static.there_can_be_only_one) {
|
||||
return error.OnlyOneAppAllowed;
|
||||
}
|
||||
|
@ -360,10 +359,9 @@ pub fn Create(
|
|||
}
|
||||
_static.unhandled_error = Context.unhandledError;
|
||||
}
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn deinit(_: *App) void {
|
||||
pub fn deinit() void {
|
||||
// we created endpoint wrappers but only tracked their interfaces
|
||||
// hence, we need to destroy the wrappers through their interfaces
|
||||
if (false) {
|
||||
|
@ -389,6 +387,15 @@ pub fn Create(
|
|||
_static.track_arenas.deinit(_static.gpa);
|
||||
}
|
||||
|
||||
// This can be resolved at comptime so *perhaps it does affect optimiazation
|
||||
pub fn callHandlerIfExist(comptime fn_name: []const u8, e: anytype, arena: Allocator, ctx: *Context, r: Request) anyerror!void {
|
||||
const EndPoint = @TypeOf(e.*);
|
||||
if (@hasDecl(EndPoint, fn_name)) {
|
||||
return @field(EndPoint, fn_name)(e, arena, ctx, r);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn get_arena() !*ArenaAllocator {
|
||||
const thread_id = std.Thread.getCurrentId();
|
||||
_static.track_arena_lock.lockShared();
|
||||
|
@ -411,7 +418,7 @@ pub fn Create(
|
|||
/// If you try to register an endpoint whose path would shadow an
|
||||
/// already registered one, you will receive an
|
||||
/// EndpointPathShadowError.
|
||||
pub fn register(_: *App, endpoint: anytype) !void {
|
||||
pub fn register(endpoint: anytype) !void {
|
||||
for (_static.endpoints.items) |other| {
|
||||
if (std.mem.startsWith(
|
||||
u8,
|
||||
|
@ -432,7 +439,7 @@ pub fn Create(
|
|||
try _static.endpoints.append(_static.gpa, &bound.interface);
|
||||
}
|
||||
|
||||
pub fn listen(_: *App, l: ListenerSettings) !void {
|
||||
pub fn listen(l: ListenerSettings) !void {
|
||||
_static.listener = HttpListener.init(.{
|
||||
.interface = l.interface,
|
||||
.port = l.port,
|
||||
|
|
Loading…
Add table
Reference in a new issue