use std::pin::Pin; use http::{Request, Response}; pub trait Layer: Send + Sync + 'static { fn layer(&self, inner: BoxedService) -> BoxedService; } impl Layer for L where L: tower_layer::Layer + Sync + Send + 'static, L::Service: Service + Send + 'static, { fn layer(&self, inner: BoxedService) -> BoxedService { BoxedService(Box::new(self.layer(inner))) } } pub trait Service { fn run( &mut self, req: http::Request, ) -> Pin< Box< dyn std::future::Future< Output = Result, server_fn::ServerFnError>, > + Send, >, >; } impl Service for S where S: tower::Service, Response = Response>, S::Future: Send + 'static, S::Error: Into, { fn run( &mut self, req: http::Request, ) -> Pin< Box< dyn std::future::Future< Output = Result, server_fn::ServerFnError>, > + Send, >, > { let fut = self.call(req); Box::pin(async move { fut.await.map_err(|err| err.into()) }) } } pub struct BoxedService(pub Box); impl tower::Service> for BoxedService { type Response = http::Response; type Error = server_fn::ServerFnError; type Future = Pin< Box< dyn std::future::Future< Output = Result, server_fn::ServerFnError>, > + Send, >, >; fn poll_ready( &mut self, _cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { Ok(()).into() } fn call(&mut self, req: Request) -> Self::Future { self.0.run(req) } }