use crate::http::error::Error;
use crate::http::response::{Body, IntoResponse};
use crate::routing::handler::{BoxedFuture, Handler, ResponseFuture};
use crate::routing::middleware::Next;
use bytes::Bytes;
use hyper::{Request, Response};
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use tower::{Layer, Service, ServiceExt};
#[derive(Debug)]
pub struct TowerServiceMarker;
#[derive(Debug, Clone)]
pub struct ServiceHandler<Svc> {
pub(crate) service: Svc,
pub(crate) strip_prefix: Option<Arc<str>>,
}
impl<Svc, RespBody, S> Handler<TowerServiceMarker, S> for ServiceHandler<Svc>
where
S: Send + Sync + 'static,
Svc: Service<Request<Bytes>, Response = Response<RespBody>> + Clone + Send + Sync + 'static,
Svc::Future: Send + 'static,
Svc::Error: Into<Error> + Send,
RespBody: hyper::body::Body<Data = Bytes> + Send + 'static,
RespBody::Error: Into<Error>,
{
fn call(self, mut req: Request<Body>, _state: Arc<S>) -> BoxedFuture {
if let Some(prefix) = &self.strip_prefix {
crate::routing::strip_uri_prefix(&mut req, prefix);
}
let mut service = self.service;
ResponseFuture::Boxed(Box::pin(async move {
let limit = crate::routing::extract::max_body_size(req.extensions());
let (parts, body) = req.into_parts();
let bytes = match body.collect_bytes(limit).await {
Ok(b) => b,
Err(e) => return e.into_response(),
};
let req = Request::from_parts(parts, bytes);
match service.ready().await {
Ok(ready) => match ready.call(req).await {
Ok(resp) => {
let (parts, body) = resp.into_parts();
Response::from_parts(parts, Body::stream(body))
}
Err(e) => Into::<Error>::into(e).into_response(),
},
Err(e) => Into::<Error>::into(e).into_response(),
}
}))
}
}
pub struct NextService<S> {
next: Option<Next<S>>,
}
impl<S> std::fmt::Debug for NextService<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NextService").finish_non_exhaustive()
}
}
impl<S> NextService<S> {
pub(crate) const fn new(next: Next<S>) -> Self {
Self { next: Some(next) }
}
}
impl<S: Send + Sync + 'static> Service<Request<Bytes>> for NextService<S> {
type Response = Response<Body>;
type Error = std::convert::Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Response<Body>, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request<Bytes>) -> Self::Future {
let next = self.next.take();
Box::pin(async move {
let Some(next) = next else {
unreachable!("NextService called more than once for the same request")
};
let (parts, bytes) = req.into_parts();
Ok(next
.run(Request::from_parts(parts, Body::full(bytes)))
.await)
})
}
}
pub(crate) fn from_tower_layer<L, S, RespBody>(
layer: L,
) -> impl Fn(Request<Body>, Next<S>) -> ResponseFuture + Clone + Send + Sync + 'static
where
S: Send + Sync + 'static,
L: Layer<NextService<S>> + Clone + Send + Sync + 'static,
L::Service: Service<Request<Bytes>, Response = Response<RespBody>> + Send + 'static,
<L::Service as Service<Request<Bytes>>>::Future: Send + 'static,
<L::Service as Service<Request<Bytes>>>::Error: Into<Error> + Send,
RespBody: hyper::body::Body<Data = Bytes> + Send + 'static,
RespBody::Error: Into<Error>,
{
move |req, next| {
let layer = layer.clone();
ResponseFuture::Boxed(Box::pin(async move {
let limit = crate::routing::extract::max_body_size(req.extensions());
let (parts, body) = req.into_parts();
let bytes = match body.collect_bytes(limit).await {
Ok(b) => b,
Err(e) => return e.into_response(),
};
let req = Request::from_parts(parts, bytes);
let mut layered = layer.layer(NextService::new(next));
match layered.ready().await {
Ok(ready) => match ready.call(req).await {
Ok(resp) => {
let (parts, body) = resp.into_parts();
Response::from_parts(parts, Body::stream(body))
}
Err(e) => Into::<Error>::into(e).into_response(),
},
Err(e) => Into::<Error>::into(e).into_response(),
}
}))
}
}
impl<S, B> Service<Request<B>> for crate::routing::CompiledRouter<S>
where
S: Clone + Send + Sync + 'static,
B: hyper::body::Body<Data = Bytes> + Send + 'static,
B::Error: Into<Error>,
{
type Response = Response<Body>;
type Error = std::convert::Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request<B>) -> Self::Future {
let (parts, body) = req.into_parts();
let req = Request::from_parts(parts, Body::stream(body));
let this = self.clone();
Box::pin(async move { Ok(this.handle_request(req).await) })
}
}
impl<B> Service<Request<B>> for crate::routing::Router<()>
where
B: hyper::body::Body<Data = Bytes> + Send + 'static,
B::Error: Into<Error>,
{
type Response = Response<Body>;
type Error = std::convert::Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
#[allow(clippy::expect_used)]
fn call(&mut self, req: Request<B>) -> Self::Future {
if self.compiled.is_none() {
let built = std::mem::take(self);
self.compiled = Some(
built
.compile()
.expect("Router compilation failed (e.g. an overlapping/duplicate route)"),
);
}
let compiled = self.compiled.as_mut().expect("just populated above");
Service::call(compiled, req)
}
}