httpx.zig is a comprehensive, high-performance HTTP library for building robust networked applications in Zig, with modern client and server primitives, support for major HTTP versions, connection pooling, and pattern-based routing. You can build your own APIs and website servers directly on top of these components; see the runnable examples in the repository: examples/, examples/static_files.zig, and examples/multi_page_website.zig.
Related Zig projects:
- For API framework support, check out api.zig.
- For web framework support, check out zix.
- For logging support, check out logly.zig.
- For data validation and serialization support, check out zigantic.
⭐ If you build with httpx.zig, make sure to give it a star. ⭐
Note
Project maturity: This project aims to be production-ready and is actively maintained. It is still a new project and not yet widely adopted. Feel free to use it in your projects.
Custom HTTP/2 & HTTP/3 implementation: Zig's standard library does not provide HTTP/2, HTTP/3, or QUIC support. httpx.zig implements these protocols entirely from scratch, including:
- HPACK header compression (RFC 7541) for HTTP/2
- HTTP/2 high-level client and server runtime paths (preface/settings/headers/data flow)
- HTTP/2 stream multiplexing and flow control (RFC 7540)
- QPACK header compression (RFC 9204) for HTTP/3
- QUIC transport framing (RFC 9000) for HTTP/3
- HTTP/3 high-level client and server runtime paths over UDP + QUIC/HTTP3/QPACK primitives
- Interop note: strict TLS-in-QUIC server negotiation expectations may vary by endpoint deployment
Features (click to expand)
| Feature | Description | Documentation |
|---|---|---|
| Protocol Support | Full runtime support for HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3 in high-level client/server APIs, plus low-level protocol primitives. | https://muhammad-fiaz.github.io/httpx.zig/api/protocol |
| Header Compression | HPACK (RFC 7541) for HTTP/2 and QPACK (RFC 9204) for HTTP/3. | https://muhammad-fiaz.github.io/httpx.zig/guide/http2 |
| Stream Multiplexing | HTTP/2 stream state machine with flow control and priority handling. | https://muhammad-fiaz.github.io/httpx.zig/api/protocol |
| Connection Pooling | Automatic reuse of TCP connections with keep-alive and health checking. | https://muhammad-fiaz.github.io/httpx.zig/guide/pooling |
| Pool Introspection | Built-in connection pool stats and per-host connection counts. | https://muhammad-fiaz.github.io/httpx.zig/api/pool |
| Pattern-based Routing | Intuitive server routing with dynamic path parameters and groups. | https://muhammad-fiaz.github.io/httpx.zig/guide/routing |
| Middleware Stack | Built-in middleware for CORS, Logging, Rate Limiting, customized Auth, and more. | https://muhammad-fiaz.github.io/httpx.zig/guide/middleware |
| Pre-Route and Global Handlers | preRoute(...) hooks and global(...) fallback handlers for complete request lifecycle control. |
https://muhammad-fiaz.github.io/httpx.zig/api/server |
| Unified Any-Method Routing | any(path, handler) to register all standard HTTP methods on one endpoint. |
https://muhammad-fiaz.github.io/httpx.zig/api/server |
| Concurrency | Parallel request patterns (race, all, any) and async task execution. |
https://muhammad-fiaz.github.io/httpx.zig/guide/concurrency |
| Interceptors | Global hooks to modify requests and responses (e.g., Auth injection). | https://muhammad-fiaz.github.io/httpx.zig/guide/interceptors |
| Smart Retries | Configurable retry policies with exponential backoff. | https://muhammad-fiaz.github.io/httpx.zig/api/client |
| JSON and HTML | Helpers for easy JSON serialization and HTML response generation. | https://muhammad-fiaz.github.io/httpx.zig/api/core |
| Core Convenience APIs | Request query-param helpers and response constructors for redirect/text/json. | https://muhammad-fiaz.github.io/httpx.zig/api/core |
| TLS/SSL | Secure connections via TLS 1.3 support. | https://muhammad-fiaz.github.io/httpx.zig/api/tls |
| Static Files | Efficient static file serving capabilities. | https://muhammad-fiaz.github.io/httpx.zig/api/server |
| Streaming and Realtime | Chunked transfer responses with optional trailers and SSE response helpers. | https://muhammad-fiaz.github.io/httpx.zig/api/server |
| Cookie APIs | First-class request/response cookie helpers for both client and server contexts. | https://muhammad-fiaz.github.io/httpx.zig/api/server |
| Security | Security headers (Helmet) and safe defaults. | https://muhammad-fiaz.github.io/httpx.zig/api/middleware |
| No External Dependencies | Pure Zig implementation for maximum portability and ease of build. | https://muhammad-fiaz.github.io/httpx.zig/guide/installation |
| Shared Common Helpers | Reusable query and cookie parsing helpers for app and library code. | https://muhammad-fiaz.github.io/httpx.zig/api/utils |
Prerequisites and Supported Platforms (click to expand)
Before using httpx.zig, ensure you have the following:
| Requirement | Version | Notes |
|---|---|---|
| Zig | 0.15.0+ | Download from ziglang.org |
| Operating System | Windows 10+, Linux, macOS | Cross-platform networking support |
httpx.zig is validated on these architectures:
| Platform | x86_64 (64-bit) | aarch64 (ARM64) | x86 (32-bit) |
|---|---|---|---|
| Linux | Yes | Yes | Yes |
| Windows | Yes | Yes | Yes |
| macOS | Yes | Yes (Apple Silicon) | No |
Zig makes cross-compilation easy. Build for any target from any host:
# Build for Linux ARM64 from Windows
zig build -Dtarget=aarch64-linux
# Build for Windows from Linux
zig build -Dtarget=x86_64-windows
# Build for macOS Apple Silicon from Linux
zig build -Dtarget=aarch64-macos
# Build for 32-bit Windows
zig build -Dtarget=x86-windowszig fetch --save https://github.com/muhammad-fiaz/httpx.zig/archive/refs/tags/0.0.7.tar.gzzig fetch --save git+https://github.com/muhammad-fiaz/httpx.zig.gitGet started quickly with a pre-configured project template:
Download Project Starter Example
Add this dependency entry to your build.zig.zon:
.dependencies = .{
.httpx = .{
.url = "https://github.com/muhammad-fiaz/httpx.zig/archive/refs/tags/0.0.7.tar.gz",
.hash = "...", // Run zig fetch --save <url> to auto-fill this.
},
},git clone https://github.com/muhammad-fiaz/httpx.zig.git
cd httpx.zig
zig buildIf you want to consume a local checkout from another project, use a local path dependency:
.dependencies = .{
.httpx = .{
.path = "../httpx.zig",
},
},After adding the dependency, import the module in your build.zig:
const httpx_dep = b.dependency("httpx", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("httpx", httpx_dep.module("httpx"));const std = @import("std");
const httpx = @import("httpx");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Create client
var client = httpx.Client.init(allocator);
defer client.deinit();
// Simple GET request
var response = try client.get("https://httpbin.org/get", .{});
defer response.deinit();
if (response.ok()) {
std.debug.print("Response: {s}\n", .{response.text() orelse ""});
}
// POST with JSON
var post_response = try client.post("https://httpbin.org/post", .{
.json = "{\"name\": \"John\"}",
});
defer post_response.deinit();
// Cookie jar helpers
try client.setCookie("session", "abc123");
_ = client.getCookie("session");
}// Top-level aliases for concise client code.
// Reuses the same allocator declared above.
var response = try httpx.fetch(allocator, "https://httpbin.org/get");
defer response.deinit();
var by_method = try httpx.send(allocator, .GET, "https://httpbin.org/headers", .{});
defer by_method.deinit();
// Additional aliases
var del_res = try httpx.delete(allocator, "https://httpbin.org/delete", .{});
defer del_res.deinit();
var opts_res = try httpx.opts(allocator, "https://httpbin.org/get", .{});
defer opts_res.deinit();// Network lifecycle (optional explicit init/deinit)
try httpx.netInit();
defer httpx.netDeinit();
// Address helpers
const one = try httpx.resolveAddress("example.com", 443);
_ = one;
const parsed = try httpx.parseHostAndPort("localhost:8080", 80);
_ = parsed;
const final_addr = try httpx.parseAndResolveAddress("127.0.0.1:9000", 80);
_ = final_addr;
const is_ip = httpx.isIpAddress("::1");
_ = is_ip;const specs = [_]httpx.RequestSpec{
.{ .method = .GET, .url = "https://httpbin.org/get" },
.{ .method = .GET, .url = "https://httpbin.org/headers" },
};
var client_for_concurrency = httpx.Client.init(allocator);
defer client_for_concurrency.deinit();
var all_results = try httpx.all(allocator, &client_for_concurrency, &specs);
defer {
for (all_results) |*r| r.deinit();
allocator.free(all_results);
}
var first_ok = try httpx.first(allocator, &client_for_concurrency, &specs);
if (first_ok) |*resp| resp.deinit();const std = @import("std");
const httpx = @import("httpx");
fn helloHandler(ctx: *httpx.Context) anyerror!httpx.Response {
return ctx.json(.{ .message = "Hello, World!" });
}
fn htmlHandler(ctx: *httpx.Context) anyerror!httpx.Response {
return ctx.html("<h1>Hello from httpx.zig!</h1>");
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var server = httpx.Server.init(allocator);
defer server.deinit();
// Add middleware
try server.use(httpx.logger());
try server.use(httpx.cors(.{}));
// Register routes
try server.get("/", helloHandler);
try server.get("/page", htmlHandler);
// Start server
try server.listen();
}The examples/ directory contains comprehensive examples for all major features:
- Basic Client:
simple_get.zig,post_json.zig - JSON Parse:
simple_get_deserialize.zig(GET + typed JSON deserialization) - Advanced Client:
custom_headers.zig,connection_pool.zig,interceptors.zig - Cookies:
cookies_demo.zig - Simplified API:
simplified_api_aliases.zig - Concurrency:
concurrent_requests.zig(Parallel/Race/All patterns) - Streaming:
streaming.zig - Server Core:
simple_server.zig,router_example.zig,middleware_example.zig - Static Assets Demo:
static_files.zig(file-based static routes + directory-based wildcard mounts for CSS/JS/images) - Website Demo:
multi_page_website.zig(full multi-page website servingindex/about/contactwith static assets) - Protocol Demos:
http2_example.zig,http2_client_runtime.zig,http2_server_runtime.zig,http3_example.zig,http3_client_runtime.zig,http3_server_runtime.zig - Networking Utility:
tcp_local.zig,udp_local.zig
To run an example:
zig build run-simple_getValidate host functionality and cross-target compatibility with these commands:
# Host runtime validation
zig build test
zig build run-all-examples
# Cross-target library compile validation
zig build build-all-targetsTo validate Linux runtime behavior (not just compilation), run Linux-target artifacts from a Linux shell (or WSL):
# Build Linux test/example artifacts
zig build test -Dtarget=x86_64-linux
zig build example-tcp_local -Dtarget=x86_64-linux
# Run on Linux/WSL
./zig-out/bin/test
./zig-out/bin/tcp_localIf a remote endpoint appears to stall, set a per-request timeout and print errors explicitly:
var response = client.get(url, .{ .timeout_ms = 10_000 }) catch |err| {
std.debug.print("request failed: {s}\n", .{@errorName(err)});
return;
};
defer response.deinit();For explicit cross-target test and example compilation, pass -Dtarget=...:
# Example: compile tests for 32-bit Windows
zig build test -Dtarget=x86-windows
# Example: compile an example for macOS ARM64
zig build example-tcp_local -Dtarget=aarch64-macosNote: this project exposes
build-all-targetsas a build step. Usezig build build-all-targets.
Run benchmarks:
zig build benchNote
Benchmark results will vary based on hardware and network conditions. The benchmark suite reports multiple rounds with min/avg/max and throughput to improve result quality.
Latest benchmark snapshot (x86_64-windows, ReleaseFast):
| Benchmark | Avg (ns/op) | Throughput (ops/sec) |
|---|---|---|
| headers_parse | 34228.26 | 29215 |
| uri_parse | 53.14 | 18818251 |
| status_lookup | 2.28 | 439313265 |
| method_lookup | 9.27 | 107889064 |
| base64_encode | 4569.04 | 218864 |
| base64_decode | 4859.87 | 205766 |
| json_builder | 4687.50 | 213333 |
| request_build | 26806.72 | 37304 |
| response_builders | 35379.08 | 28265 |
| h2_frame_header | 1.82 | 550533466 |
| h3_varint_encode | 1.22 | 816790601 |
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
zig build test - Submit a pull request
MIT License - see LICENSE for details.
