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> {}