use crate::error::Result;
pub struct Response {
pub status: u16,
pub body: String,
}
#[derive(Default, Clone)]
pub struct HeaderMap {
entries: Vec<(String, String)>,
}
impl HeaderMap {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) {
self.entries.push((key.into(), value.into()));
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
self.entries.iter().map(|(k, v)| (k.as_str(), v.as_str()))
}
}
pub trait HttpClient: Clone {
fn get(&self, url: &str, headers: &HeaderMap) -> Result<Response>;
}
#[cfg(feature = "ureq")]
#[derive(Clone)]
pub struct UreqClient;
#[cfg(feature = "ureq")]
impl HttpClient for UreqClient {
fn get(&self, url: &str, headers: &HeaderMap) -> Result<Response> {
use crate::error::Error;
let mut req = ureq::get(url).header("User-Agent", "releasekit");
for (k, v) in headers.iter() {
req = req.header(k, v);
}
let resp = req.call().map_err(|e| Error::Network(e.to_string()))?;
let status = resp.status().as_u16();
if status >= 400 {
return Err(Error::Http {
status,
url: url.to_string(),
});
}
let body = resp
.into_body()
.read_to_string()
.map_err(|e| Error::Network(e.to_string()))?;
Ok(Response { status, body })
}
}