Skip to content

Handlers ​

Handlers are functions that process HTTP requests and return responses. api.zig validates handler signatures at compile time, ensuring type safety across your entire API.

Handler Signatures ​

api.zig supports two handler signatures:

SignatureUse CaseExample
fn() ResponseStatic responses, no request data neededHealth checks, welcome pages
fn(*Context) ResponseDynamic responses, access to request dataCRUD operations, authentication

Simple Handler (No Context) ​

For handlers that don't need request data:

zig
fn hello() api.Response {
    return api.Response.text("Hello, World!");
}

fn healthCheck() api.Response {
    return api.Response.jsonRaw("{\"status\":\"healthy\"}");
}

Context Handler ​

For handlers that need access to request data:

zig
fn getUser(ctx: *api.Context) api.Response {
    const id = ctx.param("id") orelse "0";
    // Process request...
    _ = id;
    return api.Response.jsonRaw("{\"id\":1}");
}

Registering Handlers ​

zig
try app.get("/", hello);             // Simple handler
try app.get("/users/{id}", getUser); // Context handler

HTTP Methods ​

MethodFunctionTypical Use
GETapp.get()Retrieve resources
POSTapp.post()Create resources
PUTapp.put()Replace resources
PATCHapp.patch()Partial update
DELETEapp.delete()Remove resources
OPTIONSapp.options()CORS preflight
HEADapp.head()Headers only
TRACEapp.trace()Debug/diagnostic

Handler Return Types ​

Handlers must return api.Response:

MethodContent-TypeDescription
Response.jsonRaw()application/jsonRaw JSON string
Response.json()application/jsonSerialize struct
Response.text()text/plainPlain text
Response.html()text/htmlHTML content
Response.xml()application/xmlXML content
Response.err()application/jsonError response
zig
fn myHandler() api.Response {
    // JSON response
    return api.Response.jsonRaw("{\"message\":\"ok\"}");

    // Text response
    return api.Response.text("Hello");

    // HTML response
    return api.Response.html("<h1>Hello</h1>");

    // Error response
    return api.Response.err(.not_found, "{\"error\":\"Not found\"}");
}

Accessing Request Data ​

With context handlers, you can access:

MethodReturn TypeDescription
ctx.param("name")?[]const u8Path parameter
ctx.query("key")?[]const u8Query parameter
ctx.body()?[]const u8Request body
ctx.header("name")?[]const u8Request header
ctx.method()MethodHTTP method
ctx.path()[]const u8Request path
ctx.json(T)!TParse JSON body
zig
fn handler(ctx: *api.Context) api.Response {
    // Path parameters
    const id = ctx.param("id");

    // Query parameters
    const page = ctx.query("page");

    // Request body
    const body = ctx.body();

    // Headers
    const auth = ctx.header("Authorization");

    // HTTP method
    const method = ctx.method();

    // Request path
    const path = ctx.path();

    _ = .{ id, page, body, auth, method, path };
    return api.Response.text("ok");
}

Example: Complete CRUD ​

zig
fn listUsers(ctx: *api.Context) api.Response {
    _ = ctx;
    return api.Response.jsonRaw("{\"users\":[]}");
}

fn getUser(ctx: *api.Context) api.Response {
    const id = ctx.param("id") orelse "0";
    _ = id;
    return api.Response.jsonRaw("{\"id\":1,\"name\":\"John\"}");
}

fn createUser(ctx: *api.Context) api.Response {
    _ = ctx;
    return api.Response.jsonRaw("{\"id\":1}")
        .setStatus(.created);
}

fn updateUser(ctx: *api.Context) api.Response {
    _ = ctx;
    return api.Response.jsonRaw("{\"updated\":true}");
}

fn deleteUser(ctx: *api.Context) api.Response {
    _ = ctx;
    return api.Response.init().setStatus(.no_content);
}

// Register
try app.get("/users", listUsers);
try app.get("/users/{id}", getUser);
try app.post("/users", createUser);
try app.put("/users/{id}", updateUser);
try app.delete("/users/{id}", deleteUser);

Released under the MIT License.