Rpress
Framework HTTP/1.1 assíncrono em Rust, construído sobre tokio. Projetado para ser leve, seguro e pronto para produção.
Features
- Roteamento baseado em trie (estático, dinâmico, multi-method)
- Middleware (global e por grupo de rotas)
- Request body streaming via
mpsc::channel - Compressão automática gzip/brotli
- CORS nativo com builder pattern
- Rate limiting por IP
- Servir arquivos estáticos
- Cookies (parse e Set-Cookie builder)
- Graceful shutdown
- Timeouts configuráveis (leitura e idle)
- Limite de conexões simultâneas
- Headers de segurança automáticos (
X-Content-Type-Options: nosniff) - Request ID automático (
X-Request-ID)
Quick Start
use ;
async
Roteamento
As rotas usam o formato :método/caminho. Segmentos dinâmicos são prefixados com :.
Rotas estáticas
let mut routes = new;
routes.add;
Rotas com parâmetros dinâmicos
routes.add;
Multi-method no mesmo path
routes.add;
routes.add;
routes.add;
Métodos HTTP suportados
GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Middleware
Middleware global
Aplicado a todas as rotas:
app.use_middleware;
Middleware por grupo de rotas
let mut routes = new;
routes.use_middleware;
routes.add;
Request
Acessando dados do request
routes.add;
Body Streaming
Para uploads grandes, o Rpress pode transmitir o body em chunks via channel em vez de acumular tudo na memória. O threshold é configurável:
app.set_stream_threshold; // streaming para bodies > 64KB
collect_body() — Uso simples (recomendado)
Coleta o body inteiro em um Vec<u8>. Funciona tanto para bodies pequenos (já carregados) quanto para streaming:
routes.add;
body_stream() — Processamento chunk por chunk
Para processar dados sob demanda sem acumular tudo na memória:
routes.add;
Response
Builders disponíveis
// Texto simples
text
// HTML
html
// JSON
json.unwrap
// Bytes com content-type customizado
bytes
// Vazio (204 No Content)
empty
// Redirect
redirect
Encadeando modificadores
text
.with_status
.with_content_type
.with_header
Cookies
use CookieBuilder;
let cookie = new
.path
.max_age
.same_site
.http_only
.secure
.domain;
text
.set_cookie
Múltiplos Set-Cookie são suportados — cada .set_cookie() adiciona um header separado.
CORS
Configuração nativa via builder pattern:
let cors = new
.set_origins
.set_methods
.set_headers
.set_expose_headers
.set_max_age
.set_credentials;
let mut app = new;
Sem CORS:
let mut app = new;
Headers automáticos: Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Vary: Origin. Preflight OPTIONS é tratado automaticamente.
Compressão
Gzip e Brotli com negociação automática via Accept-Encoding:
app.enable_compression;
Comportamento:
- Brotli é preferido quando
Accept-Encoding: brestá presente - Gzip é usado quando
Accept-Encoding: gzipestá presente - Bodies menores que 256 bytes não são comprimidos
- Tipos já comprimidos (image/, video/, audio/*, zip, gzip) são ignorados
- SVG é comprimido normalmente
Content-EncodingeVary: Accept-Encodingsão adicionados automaticamente
Rate Limiting
Limitar requisições por IP usando token bucket:
app.set_rate_limit; // 100 requisições por 60 segundos
Quando o limite é excedido, retorna 429 Too Many Requests. Entradas expiradas são limpas automaticamente quando o store excede 10.000 registros.
Arquivos Estáticos
app.serve_static;
app.serve_static;
- Content-Type é detectado pela extensão do arquivo
- Path traversal é prevenido com
canonicalize() - Suporta: HTML, CSS, JS, JSON, imagens (PNG, JPG, GIF, SVG, WebP, ICO), fontes (WOFF, WOFF2, TTF), PDF, XML, vídeos (MP4, WebM)
Configuração Completa
use Duration;
let mut app = new;
// Capacidade do buffer de leitura (default: 40KB)
app.set_buffer_capacity;
// Timeout de leitura por request (default: 30s)
app.set_read_timeout;
// Timeout de idle entre requests keep-alive (default: 60s)
app.set_idle_timeout;
// Máximo de conexões simultâneas (default: 1024)
app.set_max_connections;
// Rate limiting
app.set_rate_limit;
// Body streaming threshold (default: 64KB)
app.set_stream_threshold;
// Compressão gzip/brotli (default: desabilitado)
app.enable_compression;
// Arquivos estáticos
app.serve_static;
// Rotas e middleware
app.use_middleware;
app.add_route_group;
// Iniciar servidor
app.listen.await?;
Controllers com handler! macro
Para organizar handlers em structs com Arc:
use handler;
;
Erros Customizados
Implemente RpressErrorExt para retornar erros com status codes customizados:
use ;
routes.add;
Handlers podem retornar:
ResponsePayload(200 implícito)Result<ResponsePayload, RpressError>Result<ResponsePayload, E>ondeE: RpressErrorExt- Qualquer
E: RpressErrorExtdiretamente (erro sem Result) ()(202 Accepted sem body)
Headers de Segurança
Aplicados automaticamente a todas as responses:
| Header | Valor |
|---|---|
X-Content-Type-Options |
nosniff |
X-Request-ID |
UUID v4 único por request |
Server |
Rpress/1.0 |
Connection |
keep-alive |
Graceful Shutdown
O servidor responde a SIGINT (Ctrl+C):
- Para de aceitar novas conexões
- Aguarda conexões ativas finalizarem
- Encerra limpo
Limites de Segurança
| Recurso | Limite |
|---|---|
| Request line | 8 KB |
| Headers (tamanho) | 8 KB |
| Headers (quantidade) | 100 |
| Body (Content-Length) | 10 MB |
| Chunk individual | 1 MB |
| Buffer de conexão | Configurável (default 40 KB) |
Licença
MIT