Vectrum
Sign In
25 lines · 1.2 KB · Rust
//! A small blocking HTTP client for the few requests the app makes itself:
//! version checks and usage hubs. Call it from a background task.

use std::time::Duration;

/// GETs `url` and returns the body, or a short description of what failed.
pub fn get(url: &str, headers: &[(&str, &str)], timeout: Duration) -> Result<String, String> {
    let agent = ureq::AgentBuilder::new().timeout(timeout).build();
    let mut request = agent.get(url).set("User-Agent", concat!("vectrum-code/", env!("CARGO_PKG_VERSION")));
    for (name, value) in headers {
        request = request.set(name, value);
    }
    match request.call() {
        Ok(response) => response.into_string().map_err(|err| err.to_string()),
        Err(ureq::Error::Status(code, response)) => {
            let body = response.into_string().unwrap_or_default();
            let detail = serde_json::from_str::<serde_json::Value>(&body)
                .ok()
                .and_then(|value| value.get("error").and_then(|error| error.as_str()).map(str::to_string))
                .unwrap_or_else(|| body.trim().chars().take(120).collect());
            Err(if detail.is_empty() { format!("HTTP {code}") } else { format!("HTTP {code}: {detail}") })
        }
        Err(err) => Err(err.to_string()),
    }
}