Para hacer peticiones HTTP en Rust el crate dominante es reqwest. Su forma habitual es asíncrona, pero trae una variante bloqueante que evita tener que aprender async para hacer una simple consulta. Esta página usa esa variante.
También te puede interesar
La dependencia
cargo add reqwest --features blocking,json cargo add serde --features derive cargo add serde_json
[dependencies]
reqwest = { version = "0.13.5", features = ["blocking", "json"] }
serde = { version = "1.0.229", features = ["derive"] }
serde_json = "1.0.151"
--no-default-features para dejarlo ligero, te quedas sin TLS y cualquier dirección https:// deja de funcionar. Las características por defecto incluyen el soporte de TLS, así que conviene dejarlas y añadir blocking y json encima.Un GET y leer el JSON de respuesta
Lo bueno de combinar reqwest con serde es que la respuesta se convierte directamente en una estructura tuya, sin pasar por texto:
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Respuesta {
url: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let r = reqwest::blocking::get("https://httpbin.org/get")?;
println!("estado: {}", r.status());
let datos: Respuesta = r.json()?;
println!("url consultada: {}", datos.url);
Ok(())
}
salidaestado: 200 OK url consultada: https://httpbin.org/get
La estructura solo declara los campos que te interesan. El JSON de httpbin trae bastantes más y serde los ignora sin protestar, que es justo lo que quieres al consumir una API ajena: si mañana añaden campos, tu programa sigue funcionando.
Un POST con cuerpo JSON
Para enviar datos hace falta un cliente, porque la petición se construye por partes:
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut cuerpo = HashMap::new();
cuerpo.insert("usuario", "ada");
cuerpo.insert("accion", "alta");
let cliente = reqwest::blocking::Client::new();
let r = cliente.post("https://httpbin.org/post").json(&cuerpo).send()?;
println!("estado: {}", r.status());
let eco: serde_json::Value = r.json()?;
println!("el servidor recibió: {}", eco["json"]);
Ok(())
}
salidaestado: 200 OK
el servidor recibió: {"accion":"alta","usuario":"ada"}
El método .json(&cuerpo) hace dos cosas: convierte el valor a JSON y pone la cabecera Content-Type correcta. httpbin devuelve lo que recibió, por eso la última línea muestra el cuerpo de vuelta.
Lo que se usa a diario
| Qué quieres | Cómo |
|---|---|
| GET sencillo | reqwest::blocking::get(url)? |
| El cuerpo como texto | .text()? |
| El cuerpo convertido a tu tipo | .json::<T>()? |
| Comprobar que fue bien | .error_for_status()? |
| Cabeceras propias | .header("Authorization", v) |
| Parámetros de consulta | .query(&[("q", "rust")]) |
| Tiempo límite | Client::builder().timeout(...) |
send() devuelve Ok aunque el servidor conteste 404 o 500: desde el punto de vista de reqwest la petición salió bien, el servidor respondió. Para que un código de error se convierta en un Err que puedas propagar con ?, hay que encadenar .error_for_status()?. Es la distinción entre fallo de transporte y respuesta negativa, y conviene no mezclarlas.El código de esta página se compiló y ejecutó con rustc 1.96.1 y reqwest 0.13.5 antes de publicarla, con peticiones reales a httpbin.org; las salidas están copiadas de la ejecución. Documentación oficial: reqwest en docs.rs.