use std::fmt;
use std::sync::Arc;
use aioduct::Runtime;
use crate::runtime::auth::Authenticator;
use crate::runtime::error::Error;
/// Async HTTP client wrapping `aioduct::Client<R>`.
pub struct Client<R: Runtime> {
inner: aioduct::Client<R>,
base_url: String,
authenticator: Option<Arc<dyn Authenticator<R>>>,
}
impl<R: Runtime> Client<R> {
/// Create a new client with the given base URL.
pub fn new(base_url: &str) -> Self {
Self {
inner: {{CLIENT_CONSTRUCTOR}},
base_url: base_url.trim_end_matches('/').to_string(),
authenticator: None,
}
}
/// Create a client with a custom `aioduct::Client`.
pub fn with_client(inner: aioduct::Client<R>, base_url: &str) -> Self {
Self {
inner,
base_url: base_url.trim_end_matches('/').to_string(),
authenticator: None,
}
}
/// Attach an authenticator to the client.
pub fn with_auth(mut self, auth: Arc<dyn Authenticator<R>>) -> Self {
self.authenticator = Some(auth);
self
}
fn full_url(&self, path: &str) -> String {
format!("{}{}", self.base_url, path)
}
/// Build a GET request.
pub fn get(&self, path: &str) -> Result<aioduct::RequestBuilder<'_, R>, Error> {
let mut req = self.inner.get(&self.full_url(path))?;
if let Some(auth) = &self.authenticator {
req = auth.authenticate(req)?;
}
Ok(req)
}
/// Build a POST request.
pub fn post(&self, path: &str) -> Result<aioduct::RequestBuilder<'_, R>, Error> {
let mut req = self.inner.post(&self.full_url(path))?;
if let Some(auth) = &self.authenticator {
req = auth.authenticate(req)?;
}
Ok(req)
}
/// Build a PUT request.
pub fn put(&self, path: &str) -> Result<aioduct::RequestBuilder<'_, R>, Error> {
let mut req = self.inner.put(&self.full_url(path))?;
if let Some(auth) = &self.authenticator {
req = auth.authenticate(req)?;
}
Ok(req)
}
/// Build a DELETE request.
pub fn delete(&self, path: &str) -> Result<aioduct::RequestBuilder<'_, R>, Error> {
let mut req = self.inner.delete(&self.full_url(path))?;
if let Some(auth) = &self.authenticator {
req = auth.authenticate(req)?;
}
Ok(req)
}
/// Build a PATCH request.
pub fn patch(&self, path: &str) -> Result<aioduct::RequestBuilder<'_, R>, Error> {
let mut req = self.inner.patch(&self.full_url(path))?;
if let Some(auth) = &self.authenticator {
req = auth.authenticate(req)?;
}
Ok(req)
}
/// Build a HEAD request.
pub fn head(&self, path: &str) -> Result<aioduct::RequestBuilder<'_, R>, Error> {
let mut req = self.inner.head(&self.full_url(path))?;
if let Some(auth) = &self.authenticator {
req = auth.authenticate(req)?;
}
Ok(req)
}
}
impl<R: Runtime> fmt::Debug for Client<R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Client")
.field("base_url", &self.base_url)
.finish()
}
}