Saltar al contenido principal

reqwest

Instalación​

  • El cliente asíncrono async(sin flag; por defecto) requiere Tokio pero para para aplicaciones o scripts que realizan pocas solicitudes es más conveniente usar con la flag blocking
  • json para deserealizar la respuesta directamente a JSON
  • default-tls por defecto, pero se puede usar rustls
cargo add reqwest -F blocking,json,rustls

Ejemplos​

El código para usar reqwest es bastante pequeño, pero los ejemplos son para demostrar un uso normal, incluyendo la manipulación de resultado y no solo las llamadas HTTP

Get​

  • No es necesario crear un cliente porque ya expone un helper ::get pero si es para varias solicitudes entonces es mejor crear el cliente.
let body: Vec<Product> = reqwest::blocking::get("https://www.junlaj.com/api/units/1")?.json()?;

println!("{body:#?}");

#[derive(Serialize, Deserialize, Debug)]
struct Unit {
id: i32,
name: String,
image: Option<String>,
}
let body = reqwest::get("https://example.com")
.await?
.text()
.await?;

println!("{body:?}");

Post Json​

  • Es necesario crear un cliente ya sea async (por defecto) o blocking
  • Dependiendo los headers que solicite la API se pueden escribir manualmente ya sea de una en una o como array, pero hay headers que son bastante comunes como Bearer que ya tiene un helper
  • Si se envía un JSON, entonces también es necesario agregar el header, pero también expone un método json() que toma el body y agrega en automático el header
// Por defecto son 30 segundos de TimeOut
let client = reqwest::blocking::Client::new();

// Algunas solicitudes, como a LLMs pueden tomar más de 30 segundos
let client = reqwest::blocking::Client::builder()
.timeout(Duration::from_secs(600))
.build()?;

// Construir el body usando serde
let body = serde_json::json!({
"prompt": "Crea un perro. Estilo cartoon. Sin fondo",
"model": "gpt-image-2.5-flare",
"size": "1024x1024",
"n": 1,
"output_format": "png",
"background": "transparent",
"quality": "high"
});

// Respuesta
let response = client.post(&url).bearer_auth(&api_key).json(&body).send()?;

// Validar estatus de la respuesta
if !response.status().is_success() {
let status = response.status();
let body: serde_json::Value = response.json()?;
eprintln!("Error: {status} - {body}");
return Err(format!("Error: {status} - {body}").into());
}

// Procesar respuesta
// ...

Respuesta Json y/o base64​

// ...

// La respuesta por defecto es .text,
// Si se desea serealizar directamente a JSON,
// entonces requiere la flag json
let response: serde_json::Value = response.json()?;

// ".ok_or" lanza el error con el contenido del response
let base64_data = response["data"][0]["b64_json"]
.as_str()
.ok_or(response.to_string())?;

// Decodificando con el crate base64
let decode = base64::engine::general_purpose::STANDARD.decode(base64_data)?;

// Guardar el archivo
// "write" es una función de conveniencia para "File::create" + "write_all"
std::fs::write("resources/images/file_name.png", decode)?;

Respuesta directamente en bytes​

  • Por ejemplo, APIs que responden directamente los bytes del audio
// ...

// Crear el contendio o bytes
let audio_bytes = response.bytes()?;

// Guardar el archivo
std::fs::write("resources/audio/test.opus", audio_bytes)?;