use std::sync::Arc;
use crate::backend::{Backend, types::BackendRequest};
use crate::{Result, body::Body};
use http::{HeaderMap, HeaderValue, Method, header};
use url::Url;
pub struct Request {
pub(crate) method: Method,
pub(crate) url: Url,
pub(crate) headers: HeaderMap,
pub(crate) body: Option<Body>,
pub(crate) backend: Backend,
pub(crate) progress_callback: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync + 'static>>,
}
impl Request {
pub async fn send(self) -> Result<crate::Response> {
let backend_request = BackendRequest {
method: self.method,
url: self.url,
headers: self.headers,
body: self.body,
progress_callback: self.progress_callback,
};
let backend_response = self.backend.execute(backend_request).await?;
Ok(crate::Response::from_backend(backend_response))
}
}
pub struct RequestBuilder {
method: Method,
url: Url,
headers: HeaderMap,
body: Option<Body>,
backend: Backend,
progress_callback: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync + 'static>>,
}
impl RequestBuilder {
pub(crate) fn new(method: Method, url: Url, backend: Backend) -> Self {
Self {
method,
url,
headers: HeaderMap::new(),
body: None,
backend,
progress_callback: None,
}
}
pub fn header(
mut self,
name: impl TryInto<http::HeaderName>,
value: impl Into<String>,
) -> crate::Result<Self> {
let header_name = name.try_into().map_err(|_| crate::Error::InvalidHeader)?;
let header_value =
HeaderValue::from_str(&value.into()).map_err(|_| crate::Error::InvalidHeader)?;
self.headers.insert(header_name, header_value);
Ok(self)
}
pub fn body(mut self, body: impl Into<Body>) -> Self {
self.body = Some(body.into());
self
}
#[cfg(feature = "json")]
pub fn json(mut self, value: impl serde::Serialize) -> Result<Self> {
self.body = Some(Body::json(value)?);
Ok(self)
}
pub fn form(
mut self,
fields: Vec<(
impl Into<std::borrow::Cow<'static, str>>,
impl Into<std::borrow::Cow<'static, str>>,
)>,
) -> Self {
self.body = Some(Body::form(fields));
self
}
pub fn text(mut self, content: impl Into<String>) -> Self {
self.body = Some(Body::text(content));
self
}
pub fn auth(mut self, auth: crate::Auth) -> Self {
let header_value =
HeaderValue::from_str(&auth.to_header_value()).expect("Invalid auth header value");
self.headers.insert(header::AUTHORIZATION, header_value);
self
}
pub fn progress<F>(mut self, callback: F) -> Self
where
F: Fn(u64, Option<u64>) + Send + Sync + 'static,
{
self.progress_callback = Some(Arc::new(callback));
self
}
pub async fn send(self) -> Result<crate::Response> {
let request = Request {
method: self.method,
url: self.url,
headers: self.headers,
body: self.body,
backend: self.backend,
progress_callback: self.progress_callback,
};
request.send().await
}
}