Skip to main content

miko/endpoint/
layer.rs

1use crate::AppError;
2use crate::extractor::from_request::FromRequest;
3use crate::handler::{FnOnceTuple, Req, TypedHandler, handler_to_svc};
4use crate::http::response::into_response::IntoResponse;
5use crate::router::HttpSvc;
6use bytes::Bytes;
7use http_body::Body;
8use http_body_util::BodyExt;
9use hyper::Response;
10use miko_core::{BoxError, MikoError};
11use std::future::Future;
12use std::sync::Arc;
13use tower::{Layer, Service, ServiceExt, util::BoxCloneService};
14
15/// Layer 扩展 trait,为 handler 和 service 提供链式调用的 layer 功能
16///
17/// # 使用示例
18///
19/// ```rust,ignore
20/// use miko::endpoint::LayerExt;
21/// use tower_http::timeout::TimeoutLayer;
22/// use std::time::Duration;
23/// use miko::handler::{handler_to_svc};
24/// use miko::router::HttpSvc;
25/// use std::sync::Arc;
26/// use tower_http::compression::CompressionLayer;
27/// use miko::handler::TypedHandler;
28///
29/// async fn my_handler() -> String {
30///     "Hello".to_string()
31/// }
32///
33/// // 链式调用多个 layer,最终得到一个 Service
34/// let endpoint = handler_to_svc(Arc::new(TypedHandler::new(my_handler, Arc::new(()))))
35///     .layer(TimeoutLayer::new(Duration::from_secs(30)))
36///     .layer(CompressionLayer::new());
37///
38/// // 使用 xxx_service 方法注册
39/// router.get_service("/api/users", endpoint);
40/// ```
41pub trait LayerExt<Svc>: Sized {
42    /// 为当前 handler 或 service 应用一个 layer,返回包装后的 Service
43    fn layer<L, B>(self, layer: L) -> HttpSvc<Req>
44    where
45        Svc: Service<Req>,
46        L: Layer<Svc>,
47        L::Service: Service<Req, Response = Response<B>> + Clone + Send + 'static,
48        <L::Service as Service<Req>>::Error: Into<AppError>,
49        B: Body<Data = Bytes> + Send + Sync + 'static,
50        B::Error: Into<BoxError>,
51        <L::Service as Service<Req>>::Future: Send + 'static;
52
53    /// 为当前 handler 或 service 应用一个 layer(使用 with_layer 别名)
54    fn with_layer<L, B>(self, layer: L) -> HttpSvc<Req>
55    where
56        Svc: Service<Req>,
57        L: Layer<Svc>,
58        L::Service: Service<Req, Response = Response<B>> + Clone + Send + 'static,
59        <L::Service as Service<Req>>::Error: Into<AppError>,
60        B: Body<Data = Bytes> + Send + Sync + 'static,
61        B::Error: Into<BoxError>,
62        <L::Service as Service<Req>>::Future: Send + 'static,
63    {
64        self.layer(layer)
65    }
66}
67
68/// 给handler应用state
69pub trait WithState<S>: Sized {
70    fn with_state<A, Fut, R, M>(self, state: S) -> HttpSvc<Req>
71    where
72        Self: FnOnceTuple<A, Output = Fut> + Clone + Send + Sync + 'static,
73        A: FromRequest<S, M> + Send + 'static,
74        Fut: Future<Output = R> + Send + 'static,
75        R: IntoResponse,
76        M: Send + Sync + 'static;
77}
78
79impl LayerExt<HttpSvc<Req>> for HttpSvc<Req> {
80    fn layer<L, B>(self, layer: L) -> HttpSvc<Req>
81    where
82        L: Layer<Self>,
83        L::Service: Service<Req, Response = Response<B>> + Clone + Send + 'static,
84        <L::Service as Service<Req>>::Error: Into<AppError>,
85        B: Body<Data = Bytes> + Send + Sync + 'static,
86        B::Error: Into<BoxError>,
87        <L::Service as Service<Req>>::Future: Send + 'static,
88    {
89        let layered_svc = layer
90            .layer(self)
91            .map_response(|resp| {
92                let (parts, body) = resp.into_parts();
93                let body = body.map_err(|e| MikoError::from(e.into())).boxed_unsync();
94                Response::from_parts(parts, body)
95            })
96            .map_err(Into::into);
97        BoxCloneService::new(layered_svc)
98    }
99}
100
101impl<F, S> WithState<S> for F
102where
103    S: Send + Sync + 'static,
104{
105    fn with_state<A, Fut, R, M>(self, state: S) -> HttpSvc<Req>
106    where
107        F: FnOnceTuple<A, Output = Fut> + Clone + Send + Sync + 'static,
108        A: FromRequest<S, M> + Send + 'static,
109        Fut: Future<Output = R> + Send + 'static,
110        R: IntoResponse,
111        M: Send + Sync + 'static,
112    {
113        let handler_arc = Arc::new(TypedHandler::new(self, Arc::new(state)));
114        handler_to_svc(handler_arc)
115    }
116}