use super::*;
use tower_service::Service;
pub struct TowerService<S, ReqBody>(pub S, std::marker::PhantomData<fn(ReqBody)>);
#[derive(Debug, thiserror::Error, displaydoc::Display)]
#[non_exhaustive]
pub enum TowerError {
ServiceError(#[source] Box<dyn std::error::Error + Send + Sync>),
BodyError(#[source] Box<dyn std::error::Error + Send + Sync>),
}
impl<S, ReqBody, ResBody> Client for TowerService<S, ReqBody>
where
S: Service<http::Request<ReqBody>, Response = http::Response<ResBody>>,
S: Clone + Send + Sync + 'static,
S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
S::Future: Future<Output = Result<http::Response<ResBody>, S::Error>> + Send + 'static,
ResBody: hyper::body::Body + Sync + Send + 'static,
ResBody::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
ResBody::Data: Sync + Send,
ReqBody: From<hyper::body::Bytes> + Sync + Send + 'static,
{
type Error = TowerError;
fn req(&self, request: Request) -> BoxedFuture<'static, Result<Response, Self::Error>> {
let mut service = self.0.clone();
Box::pin(async move {
futures::future::poll_fn(|cx| service.poll_ready(cx))
.await
.map_err(|e| TowerError::ServiceError(e.into()))?;
let fut = service.call(request.map(|b| b.into()));
let (parts, body) = fut
.await
.map_err(|e| TowerError::ServiceError(e.into()))?
.into_parts();
let b = http_body_util::BodyExt::collect(body)
.await
.map_err(|e| TowerError::BodyError(e.into()))?
.to_bytes();
Ok(http::Response::from_parts(parts, b))
})
}
}
impl<S, ReqBody> TowerService<S, ReqBody> {
pub fn new(s: S) -> Self
where S: Clone {
Self(s, std::marker::PhantomData)
}
}
impl<S: Default, ReqBody> Default for TowerService<S, ReqBody> {
fn default() -> Self { Self(<_>::default(), std::marker::PhantomData) }
}
impl<S: Clone, ReqBody> Clone for TowerService<S, ReqBody> {
fn clone(&self) -> Self { Self(self.0.clone(), std::marker::PhantomData) }
}