Spider uses a trie-based router supporting static routes, dynamic parameters (:param), and wildcards (*). Routes are chained on the server and dispatched per HTTP method.
const spider = @import("spider");
pub fn main(init: std.process.Init) !void {
var server = spider.app();
defer server.deinit();
server
.get("/", homeHandler)
.post("/users", createUser)
.get("/users/:id", getUser)
.listen(.{ .port = 8080 }) catch {};
}
Access via c.param("name"):
fn userHandler(c: *spider.Ctx) !spider.Response {
const id = c.param("id") orelse
return c.text("missing id", .{ .status = .bad_request });
return c.json(.{ .id = id }, .{});
}
Matches anything after the prefix: /assets/* matches /assets/logo.png, /assets/css/main.css, etc.
server.get("/assets/*", spider.static.serve);
Chain multiple methods on the same base path using addRoute:
server
.get("/users", listUsers)
.post("/users", createUser)
.get("/users/:id", getUser)
.put("/users/:id", updateUser)
.delete("/users/:id", deleteUser);
Use .use(middlewareFn) to apply middleware to all routes:
fn loggingMiddleware(c: *spider.Ctx, next: spider.NextFn) !spider.Response {
std.debug.print("[{s}] {s}\n", .{ c.getMethod(), c.getPath() });
return next(c);
}
server
.use(loggingMiddleware)
.get("/", homeHandler);
Use .useAt(path, middlewareFn) to scope middleware to a path pattern:
fn authMiddleware(c: *spider.Ctx, next: spider.NextFn) !spider.Response {
if (c.header("Authorization") == null) {
return c.text("Unauthorized", .{ .status = .unauthorized });
}
return next(c);
}
server
.useAt("/api/*", authMiddleware)
.get("/api/users", listUsers)
.get("/api/data", getData);
Group routes under a common prefix with shared middleware:
fn apiRoutes(s: *spider.Server, prefix: []const u8, mws: []const spider.MiddlewareFn) void {
s.addRoute(.GET, "/users", mws, listUsers);
s.addRoute(.POST, "/users", mws, createUser);
}
server.group("/api", &.{authMiddleware}, apiRoutes);
Inside the group function, use s.addRoute() to register routes with the shared middleware.
Pass middleware directly to addRoute:
server.addRoute(
.GET,
"/admin/dashboard",
&.{authMiddleware, adminMiddleware},
dashboardHandler
);
Set a global error handler with .onError():
fn errorHandler(c: *spider.Ctx, err: anyerror) !spider.Response {
return c.json(.{ .error = @errorName(err) }, .{ .status = .internal_server_error });
}
server
.onError(errorHandler)
.get("/", homeHandler);