Introducción: Por qué Rust es una excelente opción para solicitudes HTTP
\nRust es un lenguaje de programación de sistemas que ha ganado popularidad gracias a su seguridad, rendimiento y ausencia de recolector de basura. Si estás desarrollando una aplicación de red, un web scraper o un microservicio, saber cómo realizar solicitudes HTTP correctamente en Rust es una habilidad obligatoria. En este artículo, analizaremos cómo crear un cliente HTTP completo en Rust utilizando la librería reqwest, que es el estándar de facto para trabajar con HTTP en el ecosistema Rust.
Recorreremos el camino desde la instalación de dependencias hasta el manejo de errores y el trabajo con JSON. Al final del artículo, podrás escribir clientes HTTP robustos y rápidos en Rust que no te fallarán en producción.
\n\nInstalación y configuración del proyecto
\nEl primer paso es crear un nuevo proyecto y agregar la dependencia reqwest con soporte para asincronía y JSON.
cargo new rust_http_client\ncd rust_http_client\nAbre Cargo.toml y agrega:
[dependencies]\nreqwest = { version = "0.12", features = ["json"] }\ntokio = { version = "1", features = ["full"] }\nserde = { version = "1", features = ["derive"] }\nserde_json = "1"\nExplicamos cada dependencia:
\n- \n
- reqwest — el cliente HTTP principal. La bandera
jsonhabilita el soporte de serialización/deserialización. \n - tokio — el runtime asíncrono de Rust. Las solicitudes HTTP en
reqwestson asíncronas por defecto. \n - serde / serde_json — para trabajar con JSON (estructuras, serialización). \n
Ahora todo está listo para escribir código.
\n\nSolicitud GET básica: obteniendo datos del servidor
\nEmpecemos con una solicitud GET simple. Crearemos una función que obtenga datos de una API pública y los muestre en la consola.
\nuse reqwest::Error;\n\n#[tokio::main]\nasync fn main() -> Result<(), Error> {\n let url = "https://jsonplaceholder.typicode.com/posts/1";\n let response = reqwest::get(url).await?;\n\n println!("Estado: {}", response.status());\n\n let body = response.text().await?;\n println!("Cuerpo de la respuesta:\\n{}", body);\n\n Ok(())\n}\n¿Qué sucede aquí?:
\n- \n
- Usamos la macro
#[tokio::main]para ejecutar la función asíncrona. \n reqwest::get(url).await?realiza la solicitud GET. El signo?propaga el error si la solicitud falla. \nresponse.status()devuelve el estado HTTP (por ejemplo, 200 OK). \nresponse.text().await?extrae el cuerpo de la respuesta como una cadena. \n
Ejecuta el código con el comando cargo run. Verás un objeto JSON con los datos del post.
Añadiendo cabeceras y parámetros de consulta
\nEn aplicaciones reales, a menudo es necesario pasar cabeceras (por ejemplo, una clave API) o parámetros de consulta. Así es como se hace:
\nuse reqwest::Client;\nuse std::collections::HashMap;\n\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n let client = Client::new();\n\n let mut params = HashMap::new();\n params.insert("userId", "1");\n\n let response = client\n .get("https://jsonplaceholder.typicode.com/posts")\n .header("Accept", "application/json")\n .query(¶ms)\n .send()\n .await?;\n\n let posts: serde_json::Value = response.json().await?;\n println!("Número de posts: {}", posts.as_array().unwrap().len());\n\n Ok(())\n}\nPuntos clave:
\n- \n
- Creamos un
Client— este es un cliente HTTP reutilizable con un pool de conexiones. Siempre usa Client en lugar de llamadas directas areqwest::getpara código en producción. \n - El método
.header()agrega una cabecera. \n .query()acepta un diccionario de parámetros y codifica automáticamente la URL. \n.json()deserializa inmediatamente