httpx.zig is a production-ready, high-performance HTTP server library for Zig, supporting HTTP/1.1, HTTP/2, HTTP/3 (experimental), and WebSocket protocols.
- Language: Zig (requires 0.15.0+)
- Architecture: Modular design with clear separation of concerns
- Paradigm: Zero-allocation where possible, explicit memory management
- Style: Compile-time string conversion, fluent builder APIs
test "descriptive test name" {
const allocator = std.testing.allocator;
// Setup
var obj = MyStruct.init(allocator);
defer obj.deinit();
// Action
const result = try obj.doSomething();
// Assert
try std.testing.expectEqual(expected, result);
try std.testing.expectEqualStrings("expected", actual);
try std.testing.expect(condition);
try std.testing.expectError(error.SomeError, fallible_call());
}# Run all tests
zig build test
# Run with verbose output
zig build test -- --verbosezig build bench# Build library
zig build
# Build and run specific example
zig build run-simple_server
zig build run-websocket_server
zig build run-router_example
# Run all non-blocking examples
zig build run-all-examples
# Build for specific target
zig build -Dtarget=x86_64-linux
zig build -Dtarget=aarch64-macos
# Build all cross-compilation targets
zig build build-all-targets
# Generate documentation
zig build docs- Requires linking
ws2_32andmswsocksystem libraries - Async I/O is provided by ZIO runtime backend
- Async I/O is provided by ZIO runtime backend
- Async I/O is provided by ZIO runtime backend
this library is not for http client, just for http server
The main src/httpx.zig file exports all public types. When adding new types:
- Import the module:
pub const my_module = @import("path/to/module.zig");- Export specific types:
pub const MyType = my_module.MyType;
pub const myFunction = my_module.myFunction; 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
WEBSOCKET_GUID: Magic string for handshakeMAX_CONTROL_FRAME_PAYLOAD: 125 bytesDEFAULT_MAX_PAYLOAD_SIZE: 16 MB
- Static table: 61 predefined headers
- Dynamic table: configurable size (default 4096 bytes)
- Huffman encoding support
- Stream states: idle, open, half-closed, closed
- Flow control with window updates
- Priority handling
Before submitting changes:
- All tests pass (
zig build test) - No memory leaks (use
std.testing.allocator) - Proper error handling (no silent failures)
- Documentation comments for public APIs
- Consistent naming conventions
- No
@import("std").debug.printin production code paths - Proper
defer/errdeferfor resource cleanup - Cross-platform compatibility considered
-
Forgetting to deinit: Always pair
init()withdefer obj.deinit() -
Memory ownership: Be clear about who owns allocated memory; use
*_ownedflags -
Slice lifetimes: Slices don't own data; ensure underlying data outlives the slice
-
Error union propagation: Use
tryor handle errors explicitly -
Comptime vs runtime: Be aware of when values are known at compile time
-
Cross-platform differences: Test on multiple platforms or use abstraction layers