use std::collections::BTreeMap;
use crate::core::{ApiError, HttpRequest, HttpResponse, Method, Transport};
pub struct ReqwestTransport {
client: reqwest::blocking::Client,
}
impl ReqwestTransport {
pub fn new(user_agent: &str) -> Result<Self, ApiError> {
let client = reqwest::blocking::Client::builder()
.user_agent(user_agent.to_owned())
.timeout(std::time::Duration::from_secs(30))
.connect_timeout(std::time::Duration::from_secs(10))
.build()
.map_err(|e| ApiError::Network(e.to_string()))?;
Ok(Self { client })
}
}
fn to_reqwest_method(m: Method) -> reqwest::Method {
match m {
Method::Get => reqwest::Method::GET,
Method::Post => reqwest::Method::POST,
Method::Put => reqwest::Method::PUT,
Method::Delete => reqwest::Method::DELETE,
Method::Patch => reqwest::Method::PATCH,
}
}
impl Transport for ReqwestTransport {
fn execute(&self, req: HttpRequest) -> Result<HttpResponse, ApiError> {
let mut builder = self.client.request(to_reqwest_method(req.method), &req.url);
for (k, v) in &req.headers {
builder = builder.header(k, v);
}
if let Some(body) = req.body {
builder = builder.body(body);
}
let resp = builder
.send()
.map_err(|e| ApiError::Network(e.to_string()))?;
let status = resp.status().as_u16();
let mut headers = BTreeMap::new();
for (k, v) in resp.headers() {
if let Ok(s) = v.to_str() {
headers.insert(k.as_str().to_owned(), s.to_owned());
}
}
let body = resp
.bytes()
.map_err(|e| ApiError::Network(e.to_string()))?
.to_vec();
Ok(HttpResponse {
status,
headers,
body,
})
}
}