1use std::future::Future;
4use std::pin::Pin;
5
6use bytes::Bytes;
7use http_body_util::BodyExt;
8
9use super::{block_on, call, from_http_response, to_http_request, to_http_response, Body, BoxError};
10use crate::application::Application;
11use crate::middleware::Middleware;
12use crate::request::Request;
13use crate::response::Response;
14use crate::server::ConnectionInfo;
15
16pub struct TowerLayer<L> {
26 layer: L,
27}
28
29impl<L> TowerLayer<L> {
30 pub fn new(layer: L) -> TowerLayer<L> {
31 TowerLayer { layer }
32 }
33}
34
35pub struct Next<'a> {
37 app: &'a dyn Application,
38 connection: &'a ConnectionInfo,
39}
40
41impl<'a, ReqBody> tower_service::Service<http::Request<ReqBody>> for Next<'a>
42where
43 ReqBody: http_body::Body<Data = Bytes> + 'a,
44 ReqBody::Error: Into<BoxError>,
45{
46 type Response = http::Response<Body>;
47 type Error = BoxError;
48 type Future = Pin<Box<dyn Future<Output = Result<http::Response<Body>, BoxError>> + 'a>>;
49
50 fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), BoxError>> {
51 std::task::Poll::Ready(Ok(()))
52 }
53
54 fn call(&mut self, request: http::Request<ReqBody>) -> Self::Future {
55 let (app, connection) = (self.app, self.connection);
56 Box::pin(async move {
57 let (parts, body) = request.into_parts();
58 let bytes = body.collect().await.map_err(Into::into)?.to_bytes();
59 let request = super::from_http_request(http::Request::from_parts(parts, Body::full(bytes))).await?;
60 let response = app.execute(&request, connection).map_err(BoxError::from)?;
61 Ok(to_http_response(response))
62 })
63 }
64}
65
66impl<L, ResBody> Middleware for TowerLayer<L>
67where
68 L: for<'a> tower_layer::Layer<Next<'a>> + Send + Sync,
69 for<'a> <L as tower_layer::Layer<Next<'a>>>::Service: tower_service::Service<http::Request<Body>, Response = http::Response<ResBody>>,
70 for<'a> <<L as tower_layer::Layer<Next<'a>>>::Service as tower_service::Service<http::Request<Body>>>::Error: Into<BoxError>,
71 ResBody: http_body::Body<Data = Bytes> + Send + 'static,
72 ResBody::Error: Into<BoxError>,
73{
74 fn handle(&self, request: &Request, connection: &ConnectionInfo, next: &dyn Application) -> Result<Response, String> {
75 let service = self.layer.layer(Next { app: next, connection });
76 let request = to_http_request(request.clone());
77 block_on(async move {
78 let response = call(service, request).await?;
79 from_http_response(response).await
80 })
81 .map_err(|e| format!("tower layer: {e}"))
82 }
83}