reqwest & sqlx
reqwest é o cliente HTTP assíncrono ergonômico. sqlx é um toolkit SQL assíncrono com verificação em tempo de compilação. Juntos, eles cobrem a maioria das fronteiras de IO de serviço.
Receita
[dependencies]
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "macros"] }
serde = { version = "1.0", features = ["derive"] }use serde::Deserialize;
#[derive(Deserialize)]
struct Health { status: String }
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let health: Health = reqwest::get("https://httpbin.org/status/200")
.await?
.error_for_status()?
.json()
.await
.unwrap_or(Health { status: "ok".into() });
println!("{}", health.status);
Ok(())
}Quando usar isso:
- Microsserviços chamando outras APIs HTTP
- Postgres/MySQL/SQLite com pools assíncronos
- Manipuladores Axum precisando de DB + HTTP de saída
Exemplo de Trabalho
use sqlx::PgPool;
async fn count_users(pool: &PgPool) -> sqlx::Result<i64> {
let row: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM users")
.fetch_one(pool)
.await?;
Ok(row.0)
}async fn notify_webhook(url: &str, body: &str) -> reqwest::Result<()> {
reqwest::Client::new()
.post(url)
.header("content-type", "application/json")
.body(body.to_string())
.send()
.await?
.error_for_status()?;
Ok(())
}O que isso demonstra:
query_asmapeia linhas para tuplas ou structserror_for_statustransforma 4xx/5xx em erros- Ambos integram com Tokio
Mergulho Profundo
Verificação em Tempo de Compilação do sqlx
// Requer DATABASE_URL na compilação para a macro query!
let user = sqlx::query_as!(User, "SELECT id, email FROM users WHERE id = $1", id)
.fetch_one(pool)
.await?;Use o modo offline (sqlx prepare) em CI quando o DB não estiver disponível em tempo de compilação.
Links Cruzados
Armadilhas
- Recursos TLS padrão - prefira
rustls-tlspara compilações reproduzíveis. Correção: desative o OpenSSL padrão, a menos que seja necessário. - Pool de conexões por solicitação - esgota o DB. Correção: um
PgPoolno estado do aplicativo. - Cliente reqwest por chamada - perde o keep-alive. Correção: reutilize
ClientdeOnceLockou estado Axum. - sqlx sem migrações - desvio de esquema. Correção:
sqlx migrateno pipeline de implantação. - Corpos JSON grandes - picos de memória. Correção: streaming com
bytes_stream.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
hyper diretamente | HTTP Personalizado | Clientes REST Típicos |
sea-orm | Camada ORM sobre sqlx | Preferência por SQL Bruto |
tokio-postgres | Controle de nível inferior | Quer consultas em tempo de compilação |
FAQs
Cliente bloqueador reqwest?
Existe para CLIs síncronas. O cliente assíncrono é o padrão para serviços Tokio.
sqlx com SQLite?
Ative o recurso sqlite. Ótimo para testes e implantações de borda.
Timeouts?
Defina Client::builder().timeout(...) e acquire_timeout do sqlx nas opções do pool.
Segredos da string de conexão?
Carregue DATABASE_URL do ambiente em tempo de execução, nunca cometa credenciais.
Relacionado
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+.