Clientes HTTP (reqwest)
Chame APIs HTTP externas do Rust com reqwest - requisições assíncronas, JSON, timeouts e TLS com rustls.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(10))
.build()?;
let user: User = client
.get("https://api.example.com/users/1")
.bearer_auth(token)
.send()
.await?
.error_for_status()?
.json()
.await?;Quando usar isso: Qualquer serviço Rust integrando com webhooks REST, APIs de pagamento ou microsserviços internos.
Exemplo de Trabalho
use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct CreateItem { name: String }
#[derive(Deserialize)]
struct Item { id: u64, name: String }
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(15))
.user_agent("my-rust-service/1.0")
.build()?;
let created: Item = client
.post("https://httpbin.org/post")
.json(&CreateItem { name: "widget".into() })
.send()
.await?
.error_for_status()?
.json()
.await?;
let status = client.get("https://httpbin.org/status/404").send().await?;
assert_eq!(status.status(), StatusCode::NOT_FOUND);
Ok(())
}O que isso demonstra:
Clientcompartilhado reutilizado entre requisições (pool de conexões)..json()para corpos de requisição e resposta serde.error_for_status()transforma erros 4xx/5xx em erros.- Timeout global no builder.
Mergulho Profundo
Como Funciona
- reqwest usa hyper por baixo dos panos com Tokio.
- Um único
Clientpor processo mantém o pool de conexões para os hosts. - Habilite o feature
rustls-tlspara TLS sem OpenSSL.
Checklist do Cliente
| Configuração | Propósito |
|---|---|
timeout | Limite de requisição de ponta a ponta |
connect_timeout | Limite de handshake TCP/TLS |
pool_max_idle_per_host | Ajuste de keep-alive |
user_agent | Identifique seu serviço nos logs |
Notas de Rust
// Reutilize o cliente no Estado do Axum
#[derive(Clone)]
struct HttpClients { outbound: reqwest::Client }Armadilhas
- Novo Cliente por requisição - Destrói a reutilização de conexão. Correção: Construa uma vez no início.
- Sem timeout - O upstream travado bloqueia o worker para sempre. Correção: Sempre defina timeouts.
- Ignorando corpos de erro -
error_for_statusdescarta erros JSON úteis. Correção: Leia o corpo em caso de falha para log. - TLS verificado desabilitado -
danger_accept_invalid_certsem produção. Correção: Bundle de CA adequado com rustls. - Corpos de resposta enormes -
json().awaitcarrega tudo na memória. Correção: Transmita combytes_stream.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
hyper client diretamente | Controle total | Chamadas REST padrão |
ureq | Ferramentas CLI bloqueantes | Serviços assíncronos Tokio |
awc | Ecossistema Actix | Pilha Axum/Tokio |
FAQs
reqwest bloqueante?
reqwest::blocking apenas para contextos síncronos.
Cabeçalhos personalizados?
.header("X-Request-Id", id) por requisição ou cabeçalhos padrão no builder.
Multipart?
multipart::Form para uploads de arquivos.
Proxy?
Client::builder().proxy(reqwest::Proxy::http(url)?).
Retentativas?
Não embutido - veja a página de Retentativas ou o crate reqwest-middleware.
mTLS?
Identidade PKCS8 via configuração rustls no conector customizado.
HTTP/2?
Habilitado por padrão onde o servidor suporta.
Testes mockados?
wiremock ou mockito contra o código do manipulador usando um cliente injetado.
Cache DNS?
Gerenciado pelo resolvedor do sistema; conector hyper customizado para casos avançados.
Limites de taxa da API?
Respeite o cabeçalho Retry-After na camada de retentativa.
Relacionados
- TLS com rustls - Configuração HTTPS
- Retentativas, Timeouts e Backoff - Resiliência
- hyper - Nível inferior
- Melhores Práticas de Rede - Regras do cliente
- Fundamentos de Backends Web - Contraparte do servidor
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.