vidi_tower/
middleware.rs

1use tower::{Layer, Service, ServiceExt};
2use vidi_core::{Body, BoxError, Bytes, Error, Handler, HttpBody, Request, Response, Result};
3
4use crate::HandlerService;
5
6/// A [`Service`] created from a [`Handler`] by applying a Tower middleware.
7#[derive(Clone, Debug)]
8pub struct Middleware<L, H> {
9    l: L,
10    h: H,
11}
12
13impl<L, H> Middleware<L, H> {
14    /// Creates a new tower middleware.
15    pub const fn new(l: L, h: H) -> Self {
16        Self { l, h }
17    }
18}
19
20#[vidi_core::async_trait]
21impl<O, L, H> Handler<Request> for Middleware<L, H>
22where
23    L: Layer<HandlerService<H>> + Send + Sync + 'static,
24    H: Handler<Request, Output = Result<Response>> + Clone,
25    O: HttpBody + Send + 'static,
26    O::Data: Into<Bytes>,
27    O::Error: Into<BoxError>,
28    L::Service: Service<Request, Response = Response<O>> + Send + Sync + 'static,
29    <L::Service as Service<Request>>::Future: Send,
30    <L::Service as Service<Request>>::Error: Into<BoxError>,
31{
32    type Output = Result<Response>;
33
34    async fn call(&self, req: Request) -> Self::Output {
35        self.l
36            .layer(HandlerService::new(self.h.clone()))
37            .oneshot(req)
38            .await
39            .map_err(Error::boxed)
40            .map(|resp| resp.map(Body::wrap))
41    }
42}