httpz e Zap — Frameworks Web de Alta Performance em Zig
O desenvolvimento web com Zig está ganhando tração graças a frameworks como httpz e Zap que demonstram performance excepcional. Esses frameworks aproveitam o modelo de execução do Zig — sem garbage collector, com controle fino de memória e suporte nativo a I/O assíncrono — para criar servidores HTTP que rivalizam com as soluções mais rápidas em C e Rust.
httpz — O Framework Web Ergonômico
O httpz (também chamado http.zig) é o framework web mais popular do ecossistema Zig. Projetado para ser simples, rápido e idiomático, ele oferece uma API familiar para quem vem de frameworks como Express.js ou Gin.
Características Principais
- Roteamento rápido com suporte a parâmetros e wildcards
- Middleware composável
- WebSockets integrados
- Streaming de request e response
- TLS nativo
- Performance superior a frameworks Node.js e Python
Hello World com httpz
const std = @import("std");
const httpz = @import("httpz");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var server = try httpz.Server(void).init(allocator, .{
.port = 8080,
}, {});
defer server.deinit();
server.router().get("/", struct {
fn handler(_: void, response: *httpz.Response) !void {
response.body = "Olá, mundo!";
}
}.handler);
std.debug.print("Servidor rodando em http://localhost:8080\n", .{});
try server.listen();
}
Roteamento
O httpz suporta rotas com parâmetros, grupos e métodos HTTP:
const router = server.router();
// Rotas básicas
router.get("/", handleHome);
router.get("/sobre", handleSobre);
// Parâmetros de rota
router.get("/usuarios/:id", handleUsuario);
router.get("/posts/:slug", handlePost);
// Wildcards
router.get("/arquivos/*", handleArquivos);
// Métodos HTTP
router.post("/api/usuarios", criarUsuario);
router.put("/api/usuarios/:id", atualizarUsuario);
router.delete("/api/usuarios/:id", removerUsuario);
// Grupos de rotas
var api = router.group("/api/v1");
api.get("/produtos", listarProdutos);
api.post("/produtos", criarProduto);
api.get("/produtos/:id", obterProduto);
Middleware
// Middleware de logging
fn logMiddleware(
comptime Handler: type,
) httpz.Middleware(Handler) {
return struct {
pub fn handle(
_: void,
request: *httpz.Request,
response: *httpz.Response,
next: anytype,
) !void {
const inicio = std.time.milliTimestamp();
try next.handle(request, response);
const duracao = std.time.milliTimestamp() - inicio;
std.debug.print("{s} {s} - {}ms\n", .{
@tagName(request.method),
request.path,
duracao,
});
}
};
}
// Middleware de CORS
fn corsMiddleware(response: *httpz.Response) void {
response.headers.put("Access-Control-Allow-Origin", "*");
response.headers.put("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.headers.put("Access-Control-Allow-Headers", "Content-Type, Authorization");
}
Respostas JSON
const Produto = struct {
id: u32,
nome: []const u8,
preco: f64,
estoque: u32,
};
fn listarProdutos(_: void, response: *httpz.Response) !void {
const produtos = [_]Produto{
.{ .id = 1, .nome = "Teclado Mecânico", .preco = 349.90, .estoque = 50 },
.{ .id = 2, .nome = "Mouse Gamer", .preco = 199.90, .estoque = 120 },
.{ .id = 3, .nome = "Monitor 4K", .preco = 2499.90, .estoque = 15 },
};
try response.json(&produtos, .{});
}
fn obterProduto(_: void, request: *httpz.Request, response: *httpz.Response) !void {
const id_str = request.params.get("id") orelse {
response.status = .bad_request;
try response.json(.{ .erro = "ID não fornecido" }, .{});
return;
};
_ = id_str;
// Buscar produto do banco de dados
try response.json(.{
.id = 1,
.nome = "Teclado Mecânico",
.preco = 349.90,
}, .{});
}
WebSockets
fn websocketHandler(
_: void,
request: *httpz.Request,
response: *httpz.Response,
) !void {
var ws = try request.upgradeToWebSocket(response);
while (true) {
const msg = try ws.receive();
switch (msg.type) {
.text => {
try ws.send(.{ .text = msg.data });
},
.close => break,
else => {},
}
}
}
Zap — Performance Extrema
O Zap é um framework web focado em performance absoluta, construído sobre o facil.io (uma biblioteca C de I/O assíncrono). Ele frequentemente aparece no topo de benchmarks de frameworks web.
Características do Zap
- I/O assíncrono baseado em epoll/kqueue
- Zero alocações no hot path
- Event loop otimizado
- Performance comprovada em benchmarks como TechEmpower
Hello World com Zap
const std = @import("std");
const zap = @import("zap");
fn onRequest(r: zap.Request) !void {
if (r.path) |path| {
if (std.mem.eql(u8, path, "/")) {
try r.sendBody("Olá do Zap!");
return;
}
}
try r.sendBody("404 - Não encontrado");
}
pub fn main() !void {
var listener = zap.HttpListener.init(.{
.port = 3000,
.on_request = onRequest,
.log = true,
});
try listener.listen();
std.debug.print("Servidor Zap em http://localhost:3000\n", .{});
zap.start(.{
.threads = 4,
.workers = 2,
});
}
Roteamento no Zap
var router = zap.Router.init(allocator, .{
.num_threads = 4,
.on_request = onRequest,
});
router.handle_func("/api/usuarios", handleUsuarios);
router.handle_func("/api/produtos", handleProdutos);
router.handle_func("/health", handleHealth);
Benchmarks e Performance
Ambos os frameworks demonstram performance impressionante:
| Framework | Req/s (hello world) | Latência p99 | Linguagem |
|---|---|---|---|
| Zap | ~2.500.000 | 0.1ms | Zig |
| httpz | ~1.800.000 | 0.2ms | Zig |
| Actix Web | ~1.500.000 | 0.3ms | Rust |
| Gin | ~800.000 | 0.5ms | Go |
| Express | ~50.000 | 5ms | Node.js |
| Flask | ~8.000 | 25ms | Python |
Esses números variam conforme o hardware e a complexidade do payload, mas demonstram a vantagem fundamental de linguagens sem GC e com controle de memória.
Construindo uma API REST Completa
Exemplo de API REST com httpz usando drivers de banco de dados:
const std = @import("std");
const httpz = @import("httpz");
const AppState = struct {
allocator: std.mem.Allocator,
// db: *Database,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const state = AppState{
.allocator = allocator,
};
var server = try httpz.Server(AppState).init(allocator, .{
.port = 8080,
.num_threads = 8,
}, state);
defer server.deinit();
const router = server.router();
// Rotas da API
router.get("/api/health", handleHealth);
router.get("/api/usuarios", listarUsuarios);
router.post("/api/usuarios", criarUsuario);
router.get("/api/usuarios/:id", obterUsuario);
std.debug.print("API rodando em http://localhost:8080\n", .{});
try server.listen();
}
fn handleHealth(_: AppState, response: *httpz.Response) !void {
try response.json(.{ .status = "ok", .versao = "1.0.0" }, .{});
}
Qual Escolher?
httpz: Melhor para a maioria dos projetos. API mais ergonômica, documentação mais completa e comunidade maior. Ideal para APIs REST, aplicações web e microsserviços.
Zap: Melhor quando performance absoluta é prioridade. Ideal para serviços de alta carga, proxies reversos e situações onde cada milissegundo conta.
Próximos Passos
Explore as bibliotecas de clientes HTTP para consumir APIs, os drivers de banco de dados para persistência, e as bibliotecas JSON para serialização. Veja como empresas como Cloudflare usam Zig para serviços web em produção. Para receitas práticas de servidor HTTP, consulte nossas receitas.