mirror of
https://github.com/zigzap/zap.git
synced 2025-10-20 15:14:08 +00:00

zap.Endpont.Listener and zap.App now support on_error callbacks: zap.Endpont.Listener.Settings contains an `on_error` optional callback field. zap.App supports those two callbacks: /// ```zig /// const MyContext = struct { /// // You may (optionally) define the following global handlers: /// pub fn unhandledRequest(_: *MyContext, _: Allocator, _: Request) anyerror!void {} /// pub fn unhandledError(_: *MyContext, _: Request, _: anyerror) void {} /// }; /// ``` The `endpoint` example has been updated to showcase `on_error`, and the new example `app_errors` showcases `Context.unhandledError`.
124 lines
3.9 KiB
Zig
124 lines
3.9 KiB
Zig
//!
|
|
//! Part of the Zap examples.
|
|
//!
|
|
//! Build me with `zig build app_errors`.
|
|
//! Run me with `zig build run-app_errors`.
|
|
//!
|
|
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
const zap = @import("zap");
|
|
|
|
// The global Application Context
|
|
const MyContext = struct {
|
|
db_connection: []const u8,
|
|
|
|
// we don't use this
|
|
pub fn unhandledRequest(_: *MyContext, _: Allocator, _: zap.Request) anyerror!void {}
|
|
|
|
pub fn unhandledError(_: *MyContext, _: zap.Request, err: anyerror) void {
|
|
std.debug.print("\n\n\nUNHANDLED ERROR: {} !!! \n\n\n", .{err});
|
|
}
|
|
};
|
|
|
|
// A very simple endpoint handling only GET requests
|
|
const ErrorEndpoint = struct {
|
|
|
|
// zap.App.Endpoint Interface part
|
|
path: []const u8,
|
|
error_strategy: zap.Endpoint.ErrorStrategy = .raise,
|
|
|
|
// data specific for this endpoint
|
|
some_data: []const u8,
|
|
|
|
pub fn init(path: []const u8, data: []const u8) ErrorEndpoint {
|
|
return .{
|
|
.path = path,
|
|
.some_data = data,
|
|
};
|
|
}
|
|
|
|
// handle GET requests
|
|
pub fn get(_: *ErrorEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {
|
|
|
|
// we just return an error
|
|
// our error_strategy = .raise
|
|
// -> error will be raised and dispatched to MyContext.unhandledError
|
|
return error.@"Oh-No!";
|
|
}
|
|
|
|
// empty stubs for all other request methods
|
|
pub fn post(_: *ErrorEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
|
pub fn put(_: *ErrorEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
|
pub fn delete(_: *ErrorEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
|
pub fn patch(_: *ErrorEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
|
pub fn options(_: *ErrorEndpoint, _: Allocator, _: *MyContext, _: zap.Request) !void {}
|
|
};
|
|
|
|
const StopEndpoint = struct {
|
|
path: []const u8,
|
|
error_strategy: zap.Endpoint.ErrorStrategy = .log_to_response,
|
|
|
|
pub fn get(_: *StopEndpoint, _: Allocator, context: *MyContext, _: zap.Request) !void {
|
|
std.debug.print(
|
|
\\Before I stop, let me dump the app context:
|
|
\\db_connection='{s}'
|
|
\\
|
|
\\
|
|
, .{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 {
|
|
// setup allocations
|
|
var gpa: std.heap.GeneralPurposeAllocator(.{
|
|
// just to be explicit
|
|
.thread_safe = true,
|
|
}) = .{};
|
|
defer std.debug.print("\n\nLeaks detected: {}\n\n", .{gpa.deinit() != .ok});
|
|
const allocator = gpa.allocator();
|
|
|
|
// 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();
|
|
|
|
// 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);
|
|
|
|
// listen on the network
|
|
try app.listen(.{
|
|
.interface = "0.0.0.0",
|
|
.port = 3000,
|
|
});
|
|
std.debug.print("Listening on 0.0.0.0:3000\n", .{});
|
|
|
|
std.debug.print(
|
|
\\ Try me via:
|
|
\\ curl http://localhost:3000/error
|
|
\\ Stop me via:
|
|
\\ curl http://localhost:3000/stop
|
|
\\
|
|
, .{});
|
|
|
|
// start worker threads -- only 1 process!!!
|
|
zap.start(.{
|
|
.threads = 2,
|
|
.workers = 1,
|
|
});
|
|
}
|