boluo_core/service/
ext.rs

1use crate::middleware::Middleware;
2use crate::util::assert_service;
3
4use super::{
5    AndThen, ArcService, BoxCloneService, BoxService, MapErr, MapRequest, MapResponse, MapResult,
6    OrElse, Service, Then,
7};
8
9/// [`Service`] 的扩展特征,提供了一些方便的功能。
10pub trait ServiceExt<Req>: Service<Req> {
11    /// 在此服务上应用中间件。
12    ///
13    /// # 例子
14    ///
15    /// ```
16    /// use boluo_core::handler::handler_fn;
17    /// use boluo_core::middleware::middleware_fn;
18    /// use boluo_core::request::Request;
19    /// use boluo_core::service::{Service, ServiceExt};
20    ///
21    /// fn add_extension<S>(service: S) -> impl Service<Request>
22    /// where
23    ///     S: Service<Request>,
24    /// {
25    ///     service.map_request(|mut req: Request| {
26    ///         req.extensions_mut().insert("My Extension");
27    ///         req
28    ///     })
29    /// }
30    ///
31    /// let service = handler_fn(|| async {});
32    /// let service = service.with(middleware_fn(add_extension));
33    /// ```
34    fn with<T, R>(self, middleware: T) -> T::Service
35    where
36        Self: Sized,
37        T: Middleware<Self>,
38        T::Service: Service<R>,
39    {
40        assert_service(middleware.transform(self))
41    }
42
43    /// 在此服务执行完成后执行给定的异步函数。
44    ///
45    /// # 例子
46    ///
47    /// ```
48    /// use boluo_core::service::{service_fn, ServiceExt};
49    ///
50    /// #[derive(Debug)]
51    /// struct MyError;
52    ///
53    /// impl std::fmt::Display for MyError {
54    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55    ///         write!(f, "some error message")
56    ///     }
57    /// }
58    ///
59    /// impl std::error::Error for MyError {}
60    ///
61    /// async fn throw_error(_: ()) -> Result<(), MyError> {
62    ///     Err(MyError)
63    /// }
64    ///
65    /// let service = service_fn(throw_error);
66    /// let service = service.then(|result| async move {
67    ///     if let Err(err) = &result {
68    ///         // 打印错误信息。
69    ///         println!("{err}");
70    ///     }
71    ///     result
72    /// });
73    /// ```
74    fn then<F, Fut, Res, Err>(self, f: F) -> Then<Self, F>
75    where
76        Self: Sized,
77        F: Fn(Result<Self::Response, Self::Error>) -> Fut + Send + Sync,
78        Fut: Future<Output = Result<Res, Err>> + Send,
79    {
80        assert_service(Then::new(self, f))
81    }
82
83    /// 在此服务执行成功后执行给定的异步函数。
84    ///
85    /// # 例子
86    ///
87    /// ```
88    /// use boluo_core::body::Body;
89    /// use boluo_core::handler::handler_fn;
90    /// use boluo_core::service::ServiceExt;
91    /// use boluo_core::BoxError;
92    ///
93    /// async fn hello() -> &'static str {
94    ///     "Hello, World!"
95    /// }
96    ///
97    /// let service = handler_fn(hello);
98    /// let service = service.and_then(|response| async move {
99    ///     // 清空响应主体。
100    ///     Ok::<_, BoxError>(response.map(|_| Body::empty()))
101    /// });
102    /// ```
103    fn and_then<F, Fut, Res>(self, f: F) -> AndThen<Self, F>
104    where
105        Self: Sized,
106        F: Fn(Self::Response) -> Fut + Send + Sync,
107        Fut: Future<Output = Result<Res, Self::Error>> + Send,
108    {
109        assert_service(AndThen::new(self, f))
110    }
111
112    /// 在此服务执行失败后执行给定的异步函数。
113    ///
114    /// # 例子
115    ///
116    /// ```
117    /// use boluo_core::handler::handler_fn;
118    /// use boluo_core::http::StatusCode;
119    /// use boluo_core::response::IntoResponse;
120    /// use boluo_core::service::ServiceExt;
121    ///
122    /// #[derive(Debug)]
123    /// struct MyError;
124    ///
125    /// impl std::fmt::Display for MyError {
126    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127    ///         write!(f, "some error message")
128    ///     }
129    /// }
130    ///
131    /// impl std::error::Error for MyError {}
132    ///
133    /// async fn throw_error() -> Result<(), MyError> {
134    ///     Err(MyError)
135    /// }
136    ///
137    /// let service = handler_fn(throw_error);
138    /// let service = service.or_else(|err| async move {
139    ///     // 捕获错误并转换为响应。
140    ///     if let Some(e) = err.downcast_ref::<MyError>() {
141    ///         let status = StatusCode::INTERNAL_SERVER_ERROR;
142    ///         return Ok((status, format!("{e}")).into_response()?);
143    ///     }
144    ///     Err(err)
145    /// });
146    /// ```
147    fn or_else<F, Fut, Err>(self, f: F) -> OrElse<Self, F>
148    where
149        Self: Sized,
150        F: Fn(Self::Error) -> Fut + Send + Sync,
151        Fut: Future<Output = Result<Self::Response, Err>> + Send,
152    {
153        assert_service(OrElse::new(self, f))
154    }
155
156    /// 将此服务返回的结果映射为其他值。
157    ///
158    /// # 例子
159    ///
160    /// ```
161    /// use std::convert::Infallible;
162    ///
163    /// use boluo_core::response::{IntoResponse, Response};
164    /// use boluo_core::service::{service_fn, ServiceExt};
165    ///
166    /// #[derive(Debug)]
167    /// struct MyError;
168    ///
169    /// impl std::fmt::Display for MyError {
170    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171    ///         write!(f, "some error message")
172    ///     }
173    /// }
174    ///
175    /// impl std::error::Error for MyError {}
176    ///
177    /// async fn throw_error(_: ()) -> Result<(), MyError> {
178    ///     Err(MyError)
179    /// }
180    ///
181    /// let service = service_fn(throw_error);
182    /// let service = service.map_result(|result| -> Result<Response, Infallible> {
183    ///     match result {
184    ///         Ok(r) => r.into_response(),
185    ///         Err(e) => format!("{e}").into_response(),
186    ///     }
187    /// });
188    /// ```
189    fn map_result<F, Res, Err>(self, f: F) -> MapResult<Self, F>
190    where
191        Self: Sized,
192        F: Fn(Result<Self::Response, Self::Error>) -> Result<Res, Err> + Send + Sync,
193    {
194        assert_service(MapResult::new(self, f))
195    }
196
197    /// 将此服务返回的响应映射为其他值。
198    ///
199    /// # 例子
200    ///
201    /// ```
202    /// use std::convert::Infallible;
203    ///
204    /// use boluo_core::body::Body;
205    /// use boluo_core::service::{service_fn, ServiceExt};
206    ///
207    /// async fn hello(_: ()) -> Result<&'static str, Infallible> {
208    ///     Ok("Hello, World!")
209    /// }
210    ///
211    /// let service = service_fn(hello);
212    /// let service = service.map_response(|text| Body::from(text));
213    /// ```
214    fn map_response<F, Res>(self, f: F) -> MapResponse<Self, F>
215    where
216        Self: Sized,
217        F: Fn(Self::Response) -> Res + Send + Sync,
218    {
219        assert_service(MapResponse::new(self, f))
220    }
221
222    /// 将此服务返回的错误映射为其他值。
223    ///
224    /// # 例子
225    ///
226    /// ```
227    /// use boluo_core::service::{service_fn, ServiceExt};
228    /// use boluo_core::BoxError;
229    ///
230    /// #[derive(Debug)]
231    /// struct MyError;
232    ///
233    /// impl std::fmt::Display for MyError {
234    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235    ///         write!(f, "some error message")
236    ///     }
237    /// }
238    ///
239    /// impl std::error::Error for MyError {}
240    ///
241    /// async fn throw_error(_: ()) -> Result<(), MyError> {
242    ///     Err(MyError)
243    /// }
244    ///
245    /// let service = service_fn(throw_error);
246    /// let service = service.map_err(|err| BoxError::from(err));
247    /// ```
248    fn map_err<F, Err>(self, f: F) -> MapErr<Self, F>
249    where
250        Self: Sized,
251        F: Fn(Self::Error) -> Err + Send + Sync,
252    {
253        assert_service(MapErr::new(self, f))
254    }
255
256    /// 将发送给此服务的请求映射为其他值。
257    ///
258    /// # 例子
259    ///
260    /// ```
261    /// use std::convert::Infallible;
262    ///
263    /// use boluo_core::service::{service_fn, Service, ServiceExt};
264    ///
265    /// async fn echo(text: String) -> Result<String, Infallible> {
266    ///     Ok(text)
267    /// }
268    ///
269    /// let service = service_fn(echo);
270    /// let service = service.map_request(|slice: &[u8]| {
271    ///     // 将字节片转换为包含无效字符的字符串。
272    ///     String::from_utf8_lossy(slice).into_owned()
273    /// });
274    ///
275    /// let fut = service.call(b"Hello, World");
276    /// ```
277    fn map_request<F, R>(self, f: F) -> MapRequest<Self, F>
278    where
279        Self: Sized,
280        F: Fn(R) -> Req + Send + Sync,
281    {
282        assert_service(MapRequest::new(self, f))
283    }
284
285    /// 将此服务转换为 [`Service`] 特征对象并装箱。
286    ///
287    /// 更多详细信息,请参阅 [`BoxService`]。
288    fn boxed(self) -> BoxService<Req, Self::Response, Self::Error>
289    where
290        Self: Sized + 'static,
291    {
292        assert_service(BoxService::new(self))
293    }
294
295    /// 将此服务转换为 [`Service`] 特征对象并装箱。
296    ///
297    /// 更多详细信息,请参阅 [`BoxCloneService`]。
298    fn boxed_clone(self) -> BoxCloneService<Req, Self::Response, Self::Error>
299    where
300        Self: Sized + Clone + 'static,
301    {
302        assert_service(BoxCloneService::new(self))
303    }
304
305    /// 将此服务转换为 [`Service`] 特征对象并装箱。
306    ///
307    /// 更多详细信息,请参阅 [`ArcService`]。
308    fn boxed_arc(self) -> ArcService<Req, Self::Response, Self::Error>
309    where
310        Self: Sized + 'static,
311    {
312        assert_service(ArcService::new(self))
313    }
314}
315
316impl<S: ?Sized, Req> ServiceExt<Req> for S where S: Service<Req> {}