Zig HTTP router library.
Find a file
2024-11-16 18:48:06 +01:00
src Correctly add pre handlers and post handlers to routes nodes. 2024-10-18 15:09:11 +02:00
tests Root imports cleanup. 2024-10-16 11:59:06 +02:00
.gitignore Setup a router system for zap. 2024-10-10 23:50:28 +02:00
build.zig Fix zouter module configuration. 2024-10-11 12:07:03 +02:00
build.zig.zon Base zouter on zap 0.9.1. 2024-11-16 18:48:06 +01:00
LICENSE Setup a router system for zap. 2024-10-10 23:50:28 +02:00
logo.svg Add zouter logo. 2024-10-11 09:41:35 +02:00
README.md Version 0.1.1 2024-10-18 15:11:48 +02:00

Zouter logo

Zouter

Documentation | API

Zig HTTP router library

Zouter is part of zedd, a collection of useful libraries for zig.

Zouter for zap

Zouter is an HTTP router library for Zig zap HTTP server. It's made to ease the use of zap to build REST APIs.

Versions

Zouter 0.1.1 is made for zig 0.13.0 and tested with zap 0.8.0.

How to use

Install

In your project directory:

$ zig fetch --save https://code.zeptotech.net/zedd/zouter/archive/v0.1.1.tar.gz

In build.zig:

// Add zouter dependency.
const zouter = b.dependency("zouter", .{
	.target = target,
	.optimize = optimize,
});
exe.root_module.addImport("zouter", zouter.module("zouter"));

Example

Here is a quick example of how to set up a router. It is an extract from the full test code at example.zig. You may want to have a look to simple_routes.zig which shows more advanced features.

/// GET /foo/:arg/bar request handler.
fn get(route: zouter.MatchedRoute, request: zap.Request) !void {
	var bodyBuffer: [512]u8 = undefined;
	const body = try std.fmt.bufPrint(&bodyBuffer, "get: {s}", .{route.params.get("arg").?});
	try request.sendBody(body);
}

/// POST /foo/:arg/bar request handler.
fn post(route: zouter.MatchedRoute, request: zap.Request) !void {
	var bodyBuffer: [512]u8 = undefined;
	const body = try std.fmt.bufPrint(&bodyBuffer, "post: {s}", .{route.params.get("arg").?});
	try request.sendBody(body);
}

/// Setup an example router.
fn setupExampleRouter(allocator: std.mem.Allocator) !zouter.Router {
	// Initialize an example router.
	var exampleRouter = try zouter.Router.init(allocator, .{});

	// Add a route to the example router.
	try exampleRouter.route(.{
		.path = "foo",
		.children = &[_]zouter.RouteDefinition{
			.{
				.path = ":arg",
				.children = &[_]zouter.RouteDefinition{
					.{
						.path = "bar",
						.handle = .{
							.get = &get,
							.post = &post,
						},
					}
				},
			}
		},
	});

	return exampleRouter;
}

Route definition

A route only has one mandatory field: its path. If any part of a path starts with a ':', the value is taken as a dynamic variable, retrievable later with Route.params HashMap.

A route can have:

  • Children: sub-routes definitions, with a '/' between the parent and the child. It's useful to prefix a list of routes with the same path / variable.
  • Handle object: you can define a handle function for each HTTP basic request method. If you don't care about the request method, there is an any field which will be used for all undefined request methods.
  • Handle not found / error: you can define a custom functions to handle errors or not found pages inside this path.
  • Pre-handle / post-handle: these functions are started before and after the request handling in this path. It looks like middlewares and can assume the same role as most of them (e.g. a pre-handle function to check for authentication under a specific path).

Full details about route definition fields can be found in the API reference.