use std::future::Future;
use crate::{Error, Request, Response};
pub trait Backend: Send + Sync {
fn execute(&self, req: Request) -> impl Future<Output = Result<Response, Error>> + Send;
}
#[derive(Debug, Clone, Default)]
pub struct HttpClient<B> {
backend: B,
}
impl<B: Backend> HttpClient<B> {
pub fn new(backend: B) -> Self {
Self { backend }
}
pub async fn execute(&self, req: Request) -> Result<Response, Error> {
self.backend.execute(req).await
}
}
impl<B: Backend> From<B> for HttpClient<B> {
fn from(backend: B) -> Self {
Self::new(backend)
}
}
#[cfg(feature = "reqwest")]
pub use reqwest::Client as Reqwest;
#[cfg(feature = "reqwest")]
impl Backend for Reqwest {
async fn execute(&self, req: Request) -> Result<Response, Error> {
let mut builder = self.request(req.method, req.url).headers(req.headers);
if let Some(body) = req.body {
builder = builder.body(body);
}
let resp = builder.send().await?;
let status = resp.status();
let headers = resp.headers().clone();
let url = resp.url().clone();
let body = resp.bytes().await?;
Ok(Response::new(status, headers, url, body))
}
}