### Practical Router Configuration Example Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/04-router.md A comprehensive example demonstrating the setup of a router with public, API, and admin routes, including route grouping and a catch-all 404 handler. ```zig var router = try server.router(.{}); // Public routes router.get("/", index, .{}); router.get("/about", about, .{}); // API routes with common config var api = router.group("/api/v1", .{}); api.get("/users", listUsers, .{}); api.get("/users/:id", getUser, .{}); api.post("/users", createUser, .{}); // Admin routes with auth const auth = try server.middleware(AuthMiddleware, .{}); var admin = router.group("/admin", .{.middlewares = &.{auth}}); admin.get("/dashboard", dashboard, .{}); admin.get("/users/:id", adminGetUser, .{}); // Catch-all 404 router.all("/*", notFound, .{}); ``` -------------------------------- ### Running an Example Build Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Demonstrates how to build and run a specific example from the http.zig project using the Zig build system. ```bash $ zig build example_1 listening http://localhost:8800/ ``` -------------------------------- ### Basic HTTP Server Setup and Routing Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Initialize an httpz server, set custom notFound and errorHandler, define a GET route for '/api/user/:id', and start the server. This example demonstrates basic server configuration and route definition. ```zig const std = @import("std"); const httpz = @import("httpz"); pub fn main(init: std.process.Init) !void { const allocator = init.gpa; var server = try httpz.Server(void).init(init.io, allocator, .{.address = .localhost(5882)}, {}); // overwrite the default notFound handler server.notFound(notFound); // overwrite the default error handler server.errorHandler(errorHandler); var router = try server.router(.{}); // use get/post/put/head/patch/options/delete // you can also use "all" to attach to all methods router.get("/api/user/:id", getUser, .{}); // start the server in the current thread, blocking. try server.listen(); } fn getUser(req: *httpz.Request, res: *httpz.Response) !void { // status code 200 is implicit. // The json helper will automatically set the res.content_type = httpz.ContentType.JSON; // Here we're passing an inferred anonymous structure, but you can pass anytype // (so long as it can be serialized using std.json.stringify) try res.json(.{.id = req.param("id").?, .name = "Teg"}, .{}); } fn notFound(_: *httpz.Request, res: *httpz.Response) !void { res.status = 404; // you can set the body directly to a []u8, but note that the memory // must be valid beyond your handler. Use the res.arena if you need to allocate // memory for the body. res.body = "Not Found"; } // note that the error handler return `void` and not `!void` fn errorHandler(req: *httpz.Request, res: *httpz.Response, err: anyerror) void { res.status = 500; res.body = "Internal Server Error"; std.log.warn("httpz: unhandled exception for request: {s}\nErr: {}", .{req.url.raw, err}); } ``` -------------------------------- ### Route Registration Example Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/04-router.md Example of registering routes using HTTP methods like get, post, and delete. Demonstrates basic route setup with a router instance. ```zig var router = try server.router(.{}); router.get("/", index, .{}); router.post("/api/users", createUser, .{}); router.delete("/api/users/:id", deleteUser, .{}); try router.tryGet("/maybe", maybe, .{}); ``` -------------------------------- ### Quick Start Server Initialization and Routing Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/README.md Initializes an httpz server, defines a GET route for '/api/user/:id', and starts listening for requests. The handler extracts the user ID from the path and responds with JSON. ```zig const std = @import("std"); const httpz = @import("httpz"); pub fn main(init: std.process.Init) !void { const allocator = init.gpa; var server = try httpz.Server(void).init(init.io, allocator, .{ .address = .localhost(5882), }, .{}); defer { server.stop(); server.deinit(); } var router = try server.router(.{}); router.get("/api/user/:id", getUser, .{}); try server.listen(); } fn getUser(req: *httpz.Request, res: *httpz.Response) !void { const user_id = req.param("id").?; try res.json(.{.id = user_id, .name = "Alice"}, .{}); } ``` -------------------------------- ### Route Configuration Example Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/04-router.md Example showing how to apply RouteConfig to specific routes, overriding default settings for handler and dispatcher. ```zig router.get("/public", publicRoute, .{}); router.get("/admin", adminRoute, .{ .handler = &admin_handler, .dispatcher = Handler.dispatchAdmin, }); ``` -------------------------------- ### Basic HTTP Server with Routing Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Initializes an HTTP server, defines a route for '/api/user/:id', and starts listening for requests. Handles GET requests to retrieve user information. ```zig const std = @import("std"); const httpz = @import("httpz"); pub fn main(init: std.process.Init) !void { const allocator = init.gpa; // More advanced cases will use a custom "Handler" instead of "void". // The last parameter is our handler instance; since we have a "void" // handler, we passed a void ({}) value. var server = try httpz.Server(void).init(init.io, allocator, .{ // use .all(5882) to bind to all interfaces, i.e. 0.0.0.0 .address = .localhost(5882), }, .{}); defer { // clean shutdown, finishes serving any live requests server.stop(); server.deinit(); } var router = try server.router(.{}); router.get("/api/user/:id", getUser, .{}); // blocks try server.listen(); } fn getUser(req: *httpz.Request, res: *httpz.Response) !void { res.status = 200; try res.json(.{.id = req.param("id").?, .name = "Teg"}, .{}); } ``` -------------------------------- ### Complete HTTP Server Configuration Example Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md A comprehensive example demonstrating how to configure all aspects of the httpz server, including address, workers, thread pool, request/response settings, timeouts, and WebSockets. ```zig const config: httpz.Config = .{ .address = .all(8080), .workers = .{ .count = 4, .max_conn = 4096, .min_conn = 128, .large_buffer_size = 131_072, // 128KB .large_buffer_count = 32, }, .thread_pool = .{ .count = 64, .backlog = 1000, .buffer_size = 16_384, // 16KB per thread }, .request =ட்டாக{ .buffer_size = 8192, .max_body_size = 10_485_760, // 10MB .max_header_count = 64, .max_param_count = 20, .max_query_count = 50, .max_form_count = 50, .max_multiform_count = 50, .lazy_read_size = 1_048_576, // 1MB }, .response = .{ .max_header_count = 32, }, .timeout =ட்டாக{ .request = 30, .keepalive = 60, .request_count = 100, }, .websocket = .{ .compression = true, .compression_write_treshold = 1024, }, }; var server = try httpz.Server(void).init(io, allocator, config, {}); ``` -------------------------------- ### Start Server and Listen Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Starts the server and blocks until stop() is called. This is a blocking operation. Ensure to stop and deinitialize the server upon completion using defer. ```zig pub fn listen(self: *Self) !void ``` ```zig defer { server.stop(); server.deinit(); } try server.listen(); ``` -------------------------------- ### Start Server in New Thread Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Starts the server in a new thread and returns the thread handle. This is useful for testing or concurrent operations. Remember to stop the server and join the thread. ```zig pub fn listenInNewThread(self: *Self) !std.Thread ``` ```zig const thread = try server.listenInNewThread(); defer { server.stop(); thread.join(); server.deinit(); } ``` -------------------------------- ### Complete HTTP Handler Test Example Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/10-testing.md This snippet demonstrates a comprehensive set of tests for various HTTP handler scenarios, including basic GET requests, handlers with parameters, missing parameters, query parameters, and POST requests with JSON bodies. It utilizes the httpz.testing module for simulating requests and asserting responses. ```zig const std = @import("std"); const httpz = @import("httpz"); const ht = @import("httpz").testing; fn getUser(_: *httpz.Request, res: *httpz.Response) !void { res.status = 200; try res.json(.{.id = 1, .name = "Alice"}, .{}); } fn missingParam(res: *httpz.Response) !void { res.status = 400; try res.json(.{.error = "missing_parameter"}, .{}); } fn getUserWithParam(req: *httpz.Request, res: *httpz.Response) !void { const user_id = req.param("user_id") orelse return missingParam(res); res.status = 200; try res.json(.{.id = user_id}, .{}); } test "getUser returns 200 with user data" { var web_test = ht.init(.{}); defer web_test.deinit(); try getUser(web_test.req, web_test.res); try web_test.expectStatus(200); try web_test.expectJson(.{.id = 1, .name = "Alice"}); } test "getUserWithParam requires user_id" { var web_test = ht.init(.{}); defer web_test.deinit(); try getUserWithParam(web_test.req, web_test.res); try web_test.expectStatus(400); try web_test.expectJson(.{.error = "missing_parameter"}); } test "getUserWithParam returns user by id" { var web_test = ht.init(.{}); defer web_test.deinit(); web_test.param("user_id", "42"); try getUserWithParam(web_test.req, web_test.res); try web_test.expectStatus(200); try web_test.expectJson(.{.id = "42"}); } test "getUser with query params" { var web_test = ht.init(.{.request = .{.max_query_count = 10}}); defer web_test.deinit(); web_test.query("name", "Alice"); web_test.header("Accept", "application/json"); // Your handler that uses query params // ... try web_test.expectStatus(200); } test "POST with JSON body" { var web_test = ht.init(.{}); defer web_test.deinit(); try web_test.json(.{.name = "Bob", .age = 30}); // Your handler that parses JSON // ... try web_test.expectStatus(201); } ``` -------------------------------- ### Example Timeout Configuration Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md Illustrates how to set specific timeout values for requests, keepalives, and request counts within the configuration. ```zig var config = .{ .timeout = .{ .request = 30, // 30 second request timeout .keepalive = 60, // 60 second keepalive timeout .request_count = 100, // Max 100 requests per connection }, }; ``` -------------------------------- ### Define GET Route (Panics on Failure) Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Defines a GET route for a specific path. This function can panic if memory allocation fails during route creation. ```zig router.get("/", index, .{}); ``` -------------------------------- ### Example Address Configurations Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md Demonstrates how to configure the server's listening address using different variants like localhost, all interfaces, or a Unix domain socket. ```zig var config = .{ .address = .localhost(8080), }; ``` ```zig var config = .{ .address = .all(8080), }; ``` ```zig var config = .{ .address = .{ .unix = "/tmp/httpz.sock" }, }; ``` -------------------------------- ### Basic Router Initialization and Route Definition Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Initializes a server and router, then defines a GET route. This demonstrates the default configuration for handlers and middlewares. ```zig var server = try httpz.Server(Handler).init(io, allocator, .{.address = .localhost(5882)}, &handler); var router = try server.router(.{}); // Will use Handler.dispatch on the &handler instance passed to init // No middleware router.get("/route1", route1, .{}); ``` -------------------------------- ### HTTP Server Initialization with Configuration Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Example of initializing an httpz server with a custom configuration, demonstrating various address binding options and detailed settings for workers and the thread pool. ```zig try httpz.listen(allocator, &router, .{ // Listen on a localhost port. .address = .localhost(5882), // Listen on all addresses. // .address = .all(5882), // unix socket to listen on (mutually exclusive with host&port) // .address = .{ .unix = "http.sock" }, // Listen on a std.net.Address. // .address = .{ .addr = .initIp4(.{ 0, 0, 0, 0 }, 5882) }, // configure the workers which are responsible for: // 1 - accepting connections // 2 - reading and parsing requests // 3 - passing requests to the thread pool .workers = .{ // Number of worker threads // (blocking mode: handled differently) .count = 1, // Maximum number of concurrent connection each worker can handle // (blocking mode: currently ignored) .max_conn = 8_192, // Minimum number of connection states each worker should maintain // (blocking mode: currently ignored) .min_conn = 64, // A pool of larger buffers that can be used for any data larger than configured // static buffers. For example, if response headers don't fit in in // $response.header_buffer_size, a buffer will be pulled from here. // This is per-worker. .large_buffer_count = 16, // The size of each large buffer. .large_buffer_size = 65536, // Size of bytes retained for the connection arena between use. This will // result in up to `count * min_conn * retain_allocated_bytes` of memory usage. .retain_allocated_bytes = 4096, }, // configures the threadpool which processes requests. The threadpool is // where your application code runs. .thread_pool = .{ // Number threads. If your handlers are doing a lot of i/o, a higher // number might provide better throughput // (blocking mode: handled differently) .count = 32, // The maximum number of pending requests that the thread pool will accept // This applies back pressure to the above workers and ensures that, under load, // pending requests get precedence over processing new requests. .backlog = 500, // Size of the static buffer to give each thread. Memory usage will be // `count * buffer_size`. If you're making heavy use of either `req.arena` or // `res.arena`, this is likely the single easiest way to gain performance. .buffer_size = 8192, }, // options for tweaking request processing .request = .{ // Maximum request body size that we'll process. We can allocate up // to this much memory per request for the body. Internally, we might // keep this memory around for a number of requests as an optimization. .max_body_size: usize = 1_048_576, // When set, if request body is larger than this value, the body won't be // eagerly read. The application can use `req.reader()` to create a reader // to read the body. Prevents loading large bodies completely in memory. // When set, max_body_size is ignored. .lazy_read_size: ?usize = null, // This memory is allocated upfront. The request header _must_ fit into ``` -------------------------------- ### Content Type Usage Examples Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/07-types.md Demonstrates setting response content type and inferring it from file extensions or full filenames. ```zig res.content_type = .JSON; const ct = httpz.ContentType.forExtension(".html"); res.content_type = ct; const ct = httpz.ContentType.forFile("document.pdf"); res.content_type = ct; ``` -------------------------------- ### Applying Middleware to Router Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/README.md Illustrates how to apply middleware, such as CORS, to the httpz router. This example shows creating a CORS middleware and then initializing the router with it. ```zig const cors = try server.middleware(httpz.middleware.Cors, .{.origin = "*"}); var router = try server.router(.{.middlewares = &.{cors}}); ``` -------------------------------- ### listen Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Start the server and block until stop() is called. This is a blocking operation. ```APIDOC ## listen ### Description Start the server and block until `stop()` is called. This is a blocking operation. ### Signature ```zig pub fn listen(self: *Self) !void ``` ### Example: ```zig defer { server.stop(); server.deinit(); } try server.listen(); ``` ``` -------------------------------- ### Define GET Route (Error Handling) Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Defines a GET route for a specific path, returning an error instead of panicking on failure. This allows for try/catch error handling. ```zig router.tryGet("/", index, .{}); ``` -------------------------------- ### Example Worker Configuration Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md Set specific parameters for worker threads, such as the number of threads, maximum concurrent connections, and the size of large buffers. ```zig var config = .{ .workers = .{ .count = 4, .max_conn = 4096, .large_buffer_size = 131072, // 128KB }, }; ``` -------------------------------- ### Route with Static Path Segment Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Example of a route with a static path segment. ```zig router.get("/hello/users/test", route2, .{}); ``` -------------------------------- ### Global Middleware Configuration Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/06-middleware.md Configure global middleware for all routes by passing it to the server's router. This example adds CORS middleware. ```zig const cors = try server.middleware(httpz.middleware.Cors, .{ .origin = "https://example.com", .methods = "GET,POST", }); var router = try server.router(.{.middlewares = &.{cors}}); ``` -------------------------------- ### Complete WebSocket Server Example in Zig Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/08-websocket.md This snippet shows the full implementation of a WebSocket server. It includes defining the handler, setting up the server, routing requests, and handling the WebSocket upgrade. Ensure the Handler type matches the one passed to upgradeWebsocket. ```zig const std = @import("std"); const httpz = @import("httpz"); const websocket = httpz.websocket; pub const Handler = struct { pub const WebsocketContext = struct { app_id: []const u8, }; pub const WebsocketHandler = struct { conn: *websocket.Conn, app_id: []const u8, pub fn init(conn: *websocket.Conn, ctx: WebsocketContext) WebsocketHandler { return .{ .conn = conn, .app_id = ctx.app_id, }; } pub fn clientMessage(self: *WebsocketHandler, data: []const u8) !void { std.debug.print("[{s}] received: {s}\n", .{self.app_id, data}); try self.conn.write("Echo: "); try self.conn.write(data); } }; }; pub fn main(init: std.process.Init) !void { const allocator = init.gpa; var handler = Handler{}; var server = try httpz.Server(Handler).init(init.io, allocator, .{ .address = .localhost(8000), }, handler); defer { server.stop(); server.deinit(); } var router = try server.router(.{}); router.get("/ws", upgrade, .{}); router.get("/", index, .{}); try server.listen(); } fn index(_: *Handler, _: *httpz.Request, res: *httpz.Response) !void { res.content_type = .HTML; res.body = "
" ++ "" ++ ""; } fn upgrade(_: *Handler, req: *httpz.Request, res: *httpz.Response) !void { const success = try httpz.upgradeWebsocket( Handler.WebsocketHandler, req, res, Handler.WebsocketContext{.app_id = "main"}, ); if (!success) { res.status = 400; res.body = "Invalid WebSocket handshake"; } } ``` -------------------------------- ### listenInNewThread Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Start the server in a new thread and return the thread handle. Useful for testing or when you need to do other work while the server runs. ```APIDOC ## listenInNewThread ### Description Start the server in a new thread and return the thread handle. Useful for testing or when you need to do other work while the server runs. ### Signature ```zig pub fn listenInNewThread(self: *Self) !std.Thread ``` ### Returns: Thread handle that can be joined. ### Example: ```zig const thread = try server.listenInNewThread(); defer { server.stop(); thread.join(); server.deinit(); } ``` ``` -------------------------------- ### Route with Parameter Capture Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Example of a route with a captured parameter ':any'. Captured values are accessed via `req.params.get(name)`. ```zig router.get("/:any/users", route1, .{}); ``` -------------------------------- ### Example Request Configuration Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md Set specific limits and buffer sizes for incoming requests, including maximum body size, header count, and form field limits. Enables lazy reading for large bodies. ```zig var config = .{ .request = .{ .buffer_size = 8192, .max_body_size = 10_485_760, // 10MB .max_header_count = 64, .max_form_count = 32, .max_multiform_count = 32, .lazy_read_size = 1_048_576, // Stream bodies > 1MB }, }; ``` -------------------------------- ### Start Server-Sent Events Stream Synchronously Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/03-response.md Starts a Server-Sent Events stream and returns the stream object directly without spawning a new thread. This allows for synchronous writing of events. ```zig pub fn startEventStreamSync(self: *Response) !std.Io.net.Stream ``` ```zig const stream = try res.startEventStreamSync(); try stream.writeAll("data: hello\n\n"); ``` -------------------------------- ### Configure WebSocket Behavior in Server Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/08-websocket.md Example of configuring WebSocket-specific settings within the httpz server initialization, such as enabling compression and setting message size limits. ```zig var server = try httpz.Server(MyHandler).init(io, allocator, .{ .websocket = .{ .compression = true, .compression_write_treshold = 512, .max_message_size = 1_048_576, }, }, handler); ``` -------------------------------- ### Per-Route Middleware Configuration Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/06-middleware.md Apply middleware to specific routes by including it in the route's options. This example adds authentication middleware to a POST route. ```zig const auth = try server.middleware(AuthMiddleware, .{.required = true}); router.post("/protected", handler, .{.middlewares = &.{auth}}); ``` -------------------------------- ### Example Thread Pool Configuration Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md Customize the thread pool settings, including the number of handler threads, the maximum pending requests, and the size of the static buffer available to each thread. ```zig var config = .{ .thread_pool = .{ .count = 64, .backlog = 1000, .buffer_size = 16384, // 16KB per thread }, }; ``` -------------------------------- ### Configure Performance Tuning Parameters Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/README.md Shows an example of configuring performance-related settings for the httpz server. This includes adjusting worker thread counts and buffer sizes, thread pool configurations, and request processing limits like buffer size and lazy read size for large bodies. ```zig .{ .workers = .{ .count = 4, .large_buffer_size = 131_072, }, .thread_pool = .{ .count = 64, .buffer_size = 16_384, }, .request = .{ .buffer_size = 8192, .lazy_read_size = 1_048_576, }, } ``` -------------------------------- ### WebsocketHandler afterInit Method (Optional) Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/08-websocket.md An optional `afterInit` method for a `WebsocketHandler`. It is called after the handler has been initialized and can be used for setup tasks like sending a welcome message. ```zig pub fn afterInit(self: *WebsocketHandler) !void { try self.conn.write("Welcome!"); } ``` -------------------------------- ### Calculate Baseline Memory Usage Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/05-configuration.md Provides a formula and an example calculation for the total baseline memory usage of the server based on its configuration defaults. ```plaintext thread_pool.count * thread_pool.buffer_size + workers.count * workers.large_buffer_count * workers.large_buffer_size + workers.count * workers.min_conn * request.buffer_size 32 * 8192 + 1 * 16 * 65536 + 1 * 64 * 4096 = 262144 + 1048576 + 262144 = 1,572,864 bytes (1.5 MB) ``` -------------------------------- ### Storing Data in Middleware Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/06-middleware.md Demonstrates how to store request-specific data using `req.middlewares`. The example shows storing a loaded user object and retrieving it in a handler. ```zig pub const AuthMiddleware = struct { // ... pub fn execute(self: *const AuthMiddleware, req: *httpz.Request, res: *httpz.Response, executor: anytype) !void { const user = try loadUser(req); try req.middlewares.put("user", @ptrCast(user)); try executor.next(); } }; // In handler: pub fn handler(req: *httpz.Request, res: *httpz.Response) !void { const user: *User = @alignCast(@ptrCast(req.middlewares.get("user").?)); // use user } ``` -------------------------------- ### Starting a Server Side Event Stream Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Enable Server Side Events by calling `res.startEventStream()`. This method requires a context and a handler function, and automatically sets necessary headers. The response body must not be set before calling this. ```zig fn handler(_: *Request, res: *Response) !void { try res.startEventStream(StreamContext{}, StreamContext.handle); } const StreamContext = struct { fn handle(self: StreamContext, stream: std.net.Stream) void { while (true) { // some event loop stream.writeAll("event: ....\n") catch return; } } } ``` -------------------------------- ### startEventStream Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/03-response.md Starts a Server-Sent Events stream by spawning a new thread to handle the stream. It takes a context and a handler function that will be executed in the new thread. ```APIDOC ## startEventStream ### Description Start a Server-Sent Events stream. Spawns a thread to handle the stream. ### Signature ```zig pub fn startEventStream(self: *Response, ctx: anytype, comptime handler: fn (@TypeOf(ctx), std.Io.net.Stream) void) !void ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Description | |-----------|------|-------------| | ctx | `anytype` | Context passed to handler | | handler | `fn` | Function called in new thread with stream | ### Example ```zig try res.startEventStream(MyContext{}, MyContext.handleEvents); const MyContext = struct { fn handleEvents(self: MyContext, stream: std.Io.net.Stream) void { while (true) { stream.writeAll("data: message\n\n") catch break; } } }; ``` ``` -------------------------------- ### Server Type Initialization Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Creates a server type parameterized by handler type H. The handler can be void, a struct type, or a pointer type. Usage examples show initialization with void or a pointer to an App struct. ```zig pub fn Server(comptime H: type) type ``` ```zig var server = try httpz.Server(void).init(io, allocator, config, {}); var server = try httpz.Server(*App).init(io, allocator, config, &app); ``` -------------------------------- ### Implement Metrics Endpoint for Prometheus Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/README.md Provides an example of a metrics function that can be used to expose HTTP server metrics in a Prometheus-compatible format. It utilizes `httpz.writeMetrics` to write the collected metrics to a response writer. ```zig pub fn metrics(_: *httpz.Request, res: *httpz.Response) !void { const writer = res.writer(); try httpz.writeMetrics(&writer.interface); } ``` -------------------------------- ### Start Server-Sent Events Stream Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/03-response.md Initiates a Server-Sent Events stream by spawning a new thread to handle the stream. The handler function is called with the context and the stream. ```zig pub fn startEventStream(self: *Response, ctx: anytype, comptime handler: fn (@TypeOf(ctx), std.Io.net.Stream) void) !void ``` ```zig try res.startEventStream(MyContext{}, MyContext.handleEvents); const MyContext = struct { fn handleEvents(self: MyContext, stream: std.Io.net.Stream) void { while (true) { stream.writeAll("data: message\n\n") catch break; } } }; ``` -------------------------------- ### Synchronous SSE Stream Writing Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/09-server-sent-events.md Starts an SSE stream synchronously, returning the stream for direct writing. This allows for immediate writing of SSE events without spawning a new thread. ```zig pub fn getEvents(_: *httpz.Request, res: *httpz.Response) !void { const stream = try res.startEventStreamSync(); for (0..100) |i| { var buf: [50]u8 = undefined; const line = std.fmt.bufPrint(&buf, "data: #{d}\n\n", .{i}) catch continue; try stream.writeAll(line); std.time.sleep(100_000_000); // 100ms } } ``` -------------------------------- ### init Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Initialize a server instance with I/O context, allocator, configuration, and a handler. ```APIDOC ## init ### Description Initialize a server instance. ### Signature ```zig pub fn init(io: Io, allocator: Allocator, config: Config, handler: H) !Self ``` ### Parameters * **io** (`std.Io`) - I/O context for async operations * **allocator** (`Allocator`) - Memory allocator for server allocations * **config** (`Config`) - Server configuration * **handler** (`H`) - Handler instance passed to all requests ### Returns Initialized `Server(H)` instance or error. ### Example: ```zig const allocator = init.gpa; var server = try httpz.Server(void).init(init.io, allocator, .{ .address = .localhost(5882), }, {}); ``` ``` -------------------------------- ### startEventStream (Async) Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/09-server-sent-events.md Starts an SSE stream in a new thread, allowing for asynchronous handling of events. The handler function runs in a dedicated thread and writes SSE formatted messages to the stream. ```APIDOC ## startEventStream (Async) ### Description Starts an SSE stream in a new thread. The handler function is executed in a dedicated thread and is responsible for writing SSE formatted messages to the provided stream. ### Signature ```zig pub fn startEventStream( self: *Response, ctx: anytype, comptime handler: fn (@TypeOf(ctx), std.Io.net.Stream) void ) !void ``` ### Parameters #### Context - **ctx** (`anytype`) - Context passed to the handler function. - **handler** (`fn`) - The function to execute in the spawned thread. It receives the context and the stream. ### Headers This method automatically sets the following headers: - `Content-Type: text/event-stream; charset=UTF-8` - `Cache-Control: no-cache` - `Connection: keep-alive` ### Handler Function Behavior - Runs in a dedicated thread. - Receives the context and the `std.net.Stream`. - Writes messages in SSE format (e.g., `data: message\n\n`). - Supports blocking I/O on the stream. ### Example ```zig fn eventHandler(_: void, stream: std.net.Stream) void { for (0..100) |i| { var buf: [50]u8 = undefined; const line = std.fmt.bufPrint(&buf, "data: #{\d}\n\n", .{i}) catch continue; stream.writeAll(line) catch return; std.time.sleep(100_000_000); // 100ms } } pub fn getEvents(_: *httpz.Request, res: *httpz.Response) !void { try res.startEventStream({}, eventHandler); } ``` ``` -------------------------------- ### HTTP Method Route Definitions Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/04-router.md Defines routes for specific HTTP methods like GET, POST, PUT, DELETE, etc. Use `try*` variants to handle errors gracefully instead of panicking. ```zig pub fn get(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryGet(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn put(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryPut(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn post(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryPost(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn delete(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryDelete(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn patch(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryPatch(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn head(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryHead(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn options(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryOptions(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn connect(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryConnect(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void pub fn method(self: *Self, m: []const u8, path: []const u8, action: Action, config: RouteConfig) void pub fn tryMethod(self: *Self, m: []const u8, path: []const u8, action: Action, config: RouteConfig) !void pub fn all(self: *Self, path: []const u8, action: Action, config: RouteConfig) void pub fn tryAll(self: *Self, path: []const u8, action: Action, config: RouteConfig) !void ``` -------------------------------- ### Get Cookie Parser Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/02-request.md Provides access to a cookie parser with a `get(name)` method for retrieving cookie values by name. ```zig if (req.cookies().get("auth")) |auth| { // process auth cookie } ``` -------------------------------- ### Server Initialization Method Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Initializes a server instance with I/O context, memory allocator, configuration, and a handler instance. The handler is passed to all requests. ```zig pub fn init(io: Io, allocator: Allocator, config: Config, handler: H) !Self ``` ```zig const allocator = init.gpa; var server = try httpz.Server(void).init(init.io, allocator, .{ .address = .localhost(5882) }, {}); ``` -------------------------------- ### Initialize Server with Application Data Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Demonstrates initializing the httpz server with application-specific data (a database connection pool) that is passed to each action. ```zig const pg = @import("pg"); const std = @import("std"); const httpz = @import("httpz"); pub fn main(init: std.process.Init) !void { const allocator = init.gpa; var db = try pg.Pool.init(init.io, allocator, .{ .connect = .{ .port = 5432, .host = "localhost"}, .auth = .{.username = "user", .database = "db", .password = "pass"} }); defer db.deinit(); var app = App{ .db = db, }; var server = try httpz.Server(*App).init(init.io, allocator, .{.address = .localhost(5882)}, &app); var router = try server.router(.{}); router.get("/api/user/:id", getUser, .{}); try server.listen(); } const App = struct { db: *pg.Pool, }; fn getUser(app: *App, req: *httpz.Request, res: *httpz.Response) !void { const user_id = req.param("id").?; var row = try app.db.row("select name from users where id = $1", .{user_id}) orelse { res.status = 404; res.body = "Not found"; return; }; defer row.deinit() catch {}; try res.json(.{ .id = user_id, .name = row.get([]u8, 0), }, .{}); } ``` -------------------------------- ### writer Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/03-response.md Get an `std.Io.Writer` for streaming response content. ```APIDOC ## writer ### Description Get an `std.Io.Writer` for streaming response content. ### Method `*Writer` ### Returns Allocating writer pointer. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Example ```zig var ws = std.json.writeStream(&res.writer().interface, 4); try ws.beginObject(); try ws.objectField("name"); try ws.emitString("Alice"); try ws.endObject(); ``` ``` -------------------------------- ### router Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Get the router for this server to define routes. Call this before listen(). ```APIDOC ## router ### Description Get the router for this server to define routes. Call this before `listen()`. ### Signature ```zig pub fn router(self: *Self, config: RouterConfig) !*Router(H, ActionArg) ``` ### Parameters * **config** (`RouterConfig`) - Router configuration with optional global middlewares ### Returns: Mutable router pointer. ### Example: ```zig var router = try server.router(.{}); router.get("/api/user/:id", getUser, .{}); ``` ``` -------------------------------- ### Server Initialization with Generic Handler Type Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/README.md Demonstrates initializing the httpz server with a generic handler type, allowing for sharing application state or custom dispatch logic. ```zig var server = try httpz.Server(void).init(io, allocator, config, {}); var server = try httpz.Server(*App).init(io, allocator, config, &app); ``` -------------------------------- ### Get Request Body Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/02-request.md Retrieves the complete request body. Returns null if the request has no body. ```zig if (req.body()) |b| { // process body } ``` -------------------------------- ### Initialize Server and Apply CORS Middleware Globally Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Demonstrates initializing an http.zig server and applying the CORS middleware to all routes by default. The middleware configuration specifies allowed origins, methods, and headers. ```zig var server = try httpz.Server(void).init(io, allocator, .{ .address = .localhost(5882) }, .{}); const cors = try server.middleware(httpz.middleware.Cors, .{ .origin = "https://www.openmymind.net/", }); var router = try server.router(.{.middlewares = &.{cors}}); router.get("/v1/users", user, .{.middlewares = &.{cors}}); router.get("/v1/metrics", metrics, .{.middlewares = &.{cors}, .middleware_strategy = .replace}); ``` -------------------------------- ### Get Cookie Value by Name Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/02-request.md Retrieves the value of a specific cookie from the request. Requires the cookie name as input. ```zig pub fn get(self: Cookie, name: []const u8) ?[]const u8 ``` ```zig const cookies = req.cookies(); const session = cookies.get("session_id").?; ``` -------------------------------- ### Build Test Request with Parameters Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Demonstrates how to set query parameters, headers, and body for a test request using httpz.testing utilities. ```zig var web_test = ht.init(.{}); defer web_test.deinit(); web_test.param("id", "99382"); web_test.query("search", "tea"); web_test.header("Authorization", "admin"); web_test.body("over 9000!"); // OR web_test.json(.{.over = 9000}); // OR // This requires ht.init(.{.request = .{.max_form_count = 10}}) web_test.form(.{.over = "9000"}); // at this point, web_test.req has a param value, a query string value, a header value and a body. ``` -------------------------------- ### Build HTTP Responses with Body, JSON, Headers, Status, Cookies, and Streaming Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/README.md Illustrates how to construct HTTP responses, including setting a simple text body, sending JSON payloads, adding custom headers, specifying status codes, setting cookies with options like `http_only` and `secure`, and implementing streaming responses. ```zig res.body = "Hello World"; try res.json(.{.id = 1, .name = "Alice"}, .{}); res.header("X-Custom", "value"); res.status = 201; res.setStatus(.not_found); try res.setCookie("session", "token123", .{ .http_only = true, .secure = true, .path = "/" }); const stream = try res.startEventStreamSync(); try stream.writeAll("data: event\n\n"); ``` -------------------------------- ### Get Cookie by Name Source: https://github.com/karlseguin/http.zig/blob/master/readme.md Retrieve an optional cookie value from the request using its case-sensitive name. This method is part of the `req.cookies()` object. ```zig var cookies = req.cookies(); if (cookies.get("auth")) |auth| { /// ... } ``` -------------------------------- ### Get URL Path Parameter Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/02-request.md Retrieves a URL path parameter by name, as defined in the route. Returns null if the parameter is not found. ```zig // Route: /api/users/:id const user_id = req.param("id").?; ``` -------------------------------- ### Create Middleware Instance Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/01-server.md Creates a middleware instance. The middleware type must have a Config struct and an init function. The returned middleware can be used with routes. ```zig pub fn middleware(self: *Self, comptime M: type, config: M.Config) !Middleware(H) ``` ```zig const cors = try server.middleware(httpz.middleware.Cors, .{ .origin = "https://example.com", .methods = "GET,POST" }); var router = try server.router(.{.middlewares = &.{cors}}); ``` -------------------------------- ### ht.init Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/10-testing.md Initializes a test context for making HTTP requests. It takes a configuration object and returns a WebTest struct. ```APIDOC ## ht.init ### Description Initializes a test context for making HTTP requests. It takes a configuration object and returns a WebTest struct. ### Signature ```zig pub fn init(config: Config) WebTest ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **config** (`Config`) - Server config (only request/response settings matter) ### Returns - **WebTest** struct with request and response. ### Example ```zig const ht = @import("httpz").testing; var web_test = ht.init(.{}); defer web_test.deinit(); ``` ``` -------------------------------- ### Get Response Writer for Streaming Source: https://github.com/karlseguin/http.zig/blob/master/_autodocs/03-response.md Retrieves an `std.io.Writer` interface for streaming response content. This allows for writing data incrementally to the response body. ```zig var ws = std.json.writeStream(&res.writer().interface, 4); try ws.beginObject(); try ws.objectField("name"); try ws.emitString("Alice"); try ws.endObject(); ```