Dusty
Dusty is an HTTP client and server library for Zig. It's built on the standard library's
std.Io interface, and parses HTTP with
llhttp, the parser from Node.js.
It runs on any std.Io implementation that supports networking, including std.Io.Threaded from
the standard library. It was originally written for zio though,
and zio is still what we recommend for production, especially if your handlers call other services
over the network or you use WebSocket.
A lot of work has gone into making Dusty both reliable and fast. Timeouts and connection limits are
on by default, and they work on every std.Io implementation. The HTTP parsing has been checked
with HTTP Garden for differences that could lead to
request smuggling. And on HttpArena, it's among the fastest servers.
Features
- Router with path parameters, wildcards, groups and per-group middleware
- HTTP/1.0 and HTTP/1.1, with chunked transfer encoding in both directions
- Transparent gzip and deflate decoding of request and response bodies, and optional gzip compression of responses
- Server-Sent Events, and WebSocket on both the server and the client
- Static files with conditional and range requests, and assets embedded at build time
- HTTP and HTTPS client with connection pooling, and Unix socket support
- TLS on both sides, including client certificates, through tls.zig
Quick Example
A server with two routes:
const std = @import("std");
const http = @import("dusty");
const App = struct {
greeting: []const u8,
};
fn index(app: *App, res: *http.Response) !void {
try res.print(.text, "{s}, world!\n", .{app.greeting});
}
fn hello(app: *App, name: http.Param("name", []const u8), res: *http.Response) !void {
try res.print(.text, "{s}, {s}!\n", .{ app.greeting, name.value });
}
pub fn main(init: std.process.Init) !void {
var app: App = .{ .greeting = "Hello" };
var server = http.Server(App).init(init.gpa, init.io, .{
.listeners = &.{.{
.address = .{ .ip = try std.Io.net.IpAddress.parse("127.0.0.1", 8080) },
}},
}, &app);
defer server.deinit();
server.router.get("/", index);
server.router.get("/hello/:name", hello);
try server.run();
}
And a client that calls it:
const std = @import("std");
const http = @import("dusty");
pub fn main(init: std.process.Init) !void {
var client = http.Client.init(init.gpa, init.io, .{});
defer client.deinit();
var response = try client.fetch("http://127.0.0.1:8080/hello/zig", .{});
defer response.deinit();
const body = try response.body() orelse "";
std.debug.print("{d}: {s}", .{ @intFromEnum(response.status()), body });
}
See Getting Started for how to set up a project and run the server, and Making Requests for more about the client.
Zig Versions
Dusty works with Zig 0.16 and 0.17. Both are tested on Linux, macOS and Windows.
Examples
The code in these docs comes from the programs in the examples directory. examples/todo is a complete app, with templates, a PostgreSQL database and live updates over Server-Sent Events.
License
Dusty is licensed under the MIT license.