routerify/router/builder.rs
1use crate::constants;
2use crate::data_map::{DataMap, ScopedDataMap};
3use crate::middleware::{Middleware, PostMiddleware, PreMiddleware};
4use crate::route::Route;
5use crate::router::Router;
6use crate::router::{ErrHandler, ErrHandlerWithInfo, ErrHandlerWithoutInfo};
7use crate::types::RequestInfo;
8use hyper::{body::HttpBody, Method, Request, Response};
9use std::collections::HashMap;
10use std::future::Future;
11use std::sync::Arc;
12
13/// Builder for the [Router](./struct.Router.html) type.
14///
15/// This `RouterBuilder<B, E>` type accepts two type parameters: `B` and `E`.
16///
17/// * The `B` represents the response body type which will be used by route handlers and the middlewares and this body type must implement
18/// the [HttpBody](https://docs.rs/hyper/0.14.4/hyper/body/trait.HttpBody.html) trait. For an instance, `B` could be [hyper::Body](https://docs.rs/hyper/0.14.4/hyper/body/struct.Body.html)
19/// type.
20/// * The `E` represents any error type which will be used by route handlers and the middlewares. This error type must implement the [std::error::Error](https://doc.rust-lang.org/std/error/trait.Error.html).
21///
22/// # Examples
23///
24/// ```no_run
25/// use routerify::{Router, Middleware};
26/// use hyper::{Response, Request, Body};
27///
28/// async fn home_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
29/// Ok(Response::new(Body::from("home")))
30/// }
31///
32/// async fn upload_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
33/// Ok(Response::new(Body::from("upload")))
34/// }
35///
36/// async fn some_pre_middleware_handler(req: Request<Body>) -> Result<Request<Body>, hyper::Error> {
37/// Ok(req)
38/// }
39///
40/// # fn run() -> Router<Body, hyper::Error> {
41/// // Use Router::builder() method to create a new RouterBuilder instance.
42/// // We will use hyper::Body as response body type and hyper::Error as error type.
43/// let router: Router<Body, hyper::Error> = Router::builder()
44/// .get("/", home_handler)
45/// .post("/upload", upload_handler)
46/// .middleware(Middleware::pre(some_pre_middleware_handler))
47/// .build()
48/// .unwrap();
49/// # router
50/// # }
51/// # run();
52/// ```
53pub struct RouterBuilder<B, E> {
54 inner: crate::Result<BuilderInner<B, E>>,
55}
56
57struct BuilderInner<B, E> {
58 pre_middlewares: Vec<PreMiddleware<E>>,
59 routes: Vec<Route<B, E>>,
60 post_middlewares: Vec<PostMiddleware<B, E>>,
61 data_maps: HashMap<String, Vec<DataMap>>,
62 err_handler: Option<ErrHandler<B>>,
63}
64
65impl<B: HttpBody + Send + Sync + 'static, E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static>
66 RouterBuilder<B, E>
67{
68 /// Creates a new `RouterBuilder` instance with default options.
69 pub fn new() -> RouterBuilder<B, E> {
70 RouterBuilder::default()
71 }
72
73 /// Creates a new [Router](./struct.Router.html) instance from the added configuration.
74 pub fn build(self) -> crate::Result<Router<B, E>> {
75 self.inner.and_then(|inner| {
76 let scoped_data_maps = inner
77 .data_maps
78 .into_iter()
79 .map(|(path, data_map_arr)| {
80 data_map_arr
81 .into_iter()
82 .map(|data_map| ScopedDataMap::new(path.clone(), Arc::new(data_map)))
83 .collect::<Vec<crate::Result<ScopedDataMap>>>()
84 })
85 .flatten()
86 .collect::<Result<Vec<ScopedDataMap>, crate::RouteError>>()?;
87
88 Ok(Router::new(
89 inner.pre_middlewares,
90 inner.routes,
91 inner.post_middlewares,
92 scoped_data_maps,
93 inner.err_handler,
94 ))
95 })
96 }
97
98 fn and_then<F>(self, func: F) -> Self
99 where
100 F: FnOnce(BuilderInner<B, E>) -> crate::Result<BuilderInner<B, E>>,
101 {
102 RouterBuilder {
103 inner: self.inner.and_then(func),
104 }
105 }
106}
107
108impl<B: HttpBody + Send + Sync + 'static, E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static>
109 RouterBuilder<B, E>
110{
111 /// Adds a new route with `GET` method and the handler at the specified path.
112 ///
113 /// # Examples
114 ///
115 /// ```
116 /// use routerify::Router;
117 /// use hyper::{Response, Request, Body};
118 ///
119 /// async fn home_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
120 /// Ok(Response::new(Body::from("home")))
121 /// }
122 ///
123 /// # fn run() -> Router<Body, hyper::Error> {
124 /// let router = Router::builder()
125 /// .get("/", home_handler)
126 /// .build()
127 /// .unwrap();
128 /// # router
129 /// # }
130 /// # run();
131 /// ```
132 pub fn get<P, H, R>(self, path: P, handler: H) -> Self
133 where
134 P: Into<String>,
135 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
136 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
137 {
138 self.add(path, vec![Method::GET], handler)
139 }
140
141 /// Adds a new route with `GET` and `HEAD` methods and the handler at the specified path.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use routerify::Router;
147 /// use hyper::{Response, Request, Body};
148 ///
149 /// async fn home_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
150 /// Ok(Response::new(Body::from("home")))
151 /// }
152 ///
153 /// # fn run() -> Router<Body, hyper::Error> {
154 /// let router = Router::builder()
155 /// .get_or_head("/", home_handler)
156 /// .build()
157 /// .unwrap();
158 /// # router
159 /// # }
160 /// # run();
161 /// ```
162 pub fn get_or_head<P, H, R>(self, path: P, handler: H) -> Self
163 where
164 P: Into<String>,
165 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
166 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
167 {
168 self.add(path, vec![Method::GET, Method::HEAD], handler)
169 }
170
171 /// Adds a new route with `POST` method and the handler at the specified path.
172 ///
173 /// # Examples
174 ///
175 /// ```
176 /// use routerify::Router;
177 /// use hyper::{Response, Request, Body};
178 ///
179 /// async fn file_upload_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
180 /// Ok(Response::new(Body::from("File uploader")))
181 /// }
182 ///
183 /// # fn run() -> Router<Body, hyper::Error> {
184 /// let router = Router::builder()
185 /// .post("/upload", file_upload_handler)
186 /// .build()
187 /// .unwrap();
188 /// # router
189 /// # }
190 /// # run();
191 /// ```
192 pub fn post<P, H, R>(self, path: P, handler: H) -> Self
193 where
194 P: Into<String>,
195 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
196 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
197 {
198 self.add(path, vec![Method::POST], handler)
199 }
200
201 /// Adds a new route with `PUT` method and the handler at the specified path.
202 ///
203 /// # Examples
204 ///
205 /// ```
206 /// use routerify::Router;
207 /// use hyper::{Response, Request, Body};
208 ///
209 /// async fn file_upload_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
210 /// Ok(Response::new(Body::from("File uploader")))
211 /// }
212 ///
213 /// # fn run() -> Router<Body, hyper::Error> {
214 /// let router = Router::builder()
215 /// .put("/upload", file_upload_handler)
216 /// .build()
217 /// .unwrap();
218 /// # router
219 /// # }
220 /// # run();
221 /// ```
222 pub fn put<P, H, R>(self, path: P, handler: H) -> Self
223 where
224 P: Into<String>,
225 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
226 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
227 {
228 self.add(path, vec![Method::PUT], handler)
229 }
230
231 /// Adds a new route with `DELETE` method and the handler at the specified path.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use routerify::Router;
237 /// use hyper::{Response, Request, Body};
238 ///
239 /// async fn delete_file_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
240 /// Ok(Response::new(Body::from("Delete file")))
241 /// }
242 ///
243 /// # fn run() -> Router<Body, hyper::Error> {
244 /// let router = Router::builder()
245 /// .delete("/delete-file", delete_file_handler)
246 /// .build()
247 /// .unwrap();
248 /// # router
249 /// # }
250 /// # run();
251 /// ```
252 pub fn delete<P, H, R>(self, path: P, handler: H) -> Self
253 where
254 P: Into<String>,
255 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
256 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
257 {
258 self.add(path, vec![Method::DELETE], handler)
259 }
260
261 /// Adds a new route with `HEAD` method and the handler at the specified path.
262 ///
263 /// # Examples
264 ///
265 /// ```
266 /// use routerify::Router;
267 /// use hyper::{Response, Request, Body};
268 ///
269 /// async fn a_head_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
270 /// Ok(Response::new(Body::empty()))
271 /// }
272 ///
273 /// # fn run() -> Router<Body, hyper::Error> {
274 /// let router = Router::builder()
275 /// .head("/fetch-data", a_head_handler)
276 /// .build()
277 /// .unwrap();
278 /// # router
279 /// # }
280 /// # run();
281 /// ```
282 pub fn head<P, H, R>(self, path: P, handler: H) -> Self
283 where
284 P: Into<String>,
285 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
286 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
287 {
288 self.add(path, vec![Method::HEAD], handler)
289 }
290
291 /// Adds a new route with `TRACE` method and the handler at the specified path.
292 ///
293 /// # Examples
294 ///
295 /// ```
296 /// use routerify::Router;
297 /// use hyper::{Response, Request, Body};
298 ///
299 /// async fn trace_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
300 /// Ok(Response::new(Body::empty()))
301 /// }
302 ///
303 /// # fn run() -> Router<Body, hyper::Error> {
304 /// let router = Router::builder()
305 /// .trace("/abc", trace_handler)
306 /// .build()
307 /// .unwrap();
308 /// # router
309 /// # }
310 /// # run();
311 /// ```
312 pub fn trace<P, H, R>(self, path: P, handler: H) -> Self
313 where
314 P: Into<String>,
315 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
316 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
317 {
318 self.add(path, vec![Method::TRACE], handler)
319 }
320
321 /// Adds a new route with `CONNECT` method and the handler at the specified path.
322 ///
323 /// # Examples
324 ///
325 /// ```
326 /// use routerify::Router;
327 /// use hyper::{Response, Request, Body};
328 ///
329 /// async fn connect_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
330 /// Ok(Response::new(Body::empty()))
331 /// }
332 ///
333 /// # fn run() -> Router<Body, hyper::Error> {
334 /// let router = Router::builder()
335 /// .connect("/abc", connect_handler)
336 /// .build()
337 /// .unwrap();
338 /// # router
339 /// # }
340 /// # run();
341 /// ```
342 pub fn connect<P, H, R>(self, path: P, handler: H) -> Self
343 where
344 P: Into<String>,
345 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
346 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
347 {
348 self.add(path, vec![Method::CONNECT], handler)
349 }
350
351 /// Adds a new route with `PATCH` method and the handler at the specified path.
352 ///
353 /// # Examples
354 ///
355 /// ```
356 /// use routerify::Router;
357 /// use hyper::{Response, Request, Body};
358 ///
359 /// async fn update_data_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
360 /// Ok(Response::new(Body::from("Data updater")))
361 /// }
362 ///
363 /// # fn run() -> Router<Body, hyper::Error> {
364 /// let router = Router::builder()
365 /// .patch("/update-data", update_data_handler)
366 /// .build()
367 /// .unwrap();
368 /// # router
369 /// # }
370 /// # run();
371 /// ```
372 pub fn patch<P, H, R>(self, path: P, handler: H) -> Self
373 where
374 P: Into<String>,
375 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
376 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
377 {
378 self.add(path, vec![Method::PATCH], handler)
379 }
380
381 /// Adds a new route with `OPTIONS` method and the handler at the specified path.
382 ///
383 /// # Examples
384 ///
385 /// ```
386 /// use routerify::Router;
387 /// use hyper::{Response, Request, Body};
388 ///
389 /// async fn options_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
390 /// Ok(Response::new(Body::empty()))
391 /// }
392 ///
393 /// # fn run() -> Router<Body, hyper::Error> {
394 /// let router = Router::builder()
395 /// .options("/abc", options_handler)
396 /// .build()
397 /// .unwrap();
398 /// # router
399 /// # }
400 /// # run();
401 /// ```
402 pub fn options<P, H, R>(self, path: P, handler: H) -> Self
403 where
404 P: Into<String>,
405 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
406 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
407 {
408 self.add(path, vec![Method::OPTIONS], handler)
409 }
410
411 /// Adds a new route with any method type and the handler at the `/*` path. It will accept any kind of request. It can be used to send
412 /// response for any non-existing routes i.e. for `404` pages.
413 ///
414 /// # Examples
415 ///
416 /// ```
417 /// use routerify::Router;
418 /// use hyper::{Response, Request, Body, StatusCode};
419 ///
420 /// async fn home_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
421 /// Ok(Response::new(Body::from("home")))
422 /// }
423 ///
424 /// async fn handler_404(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
425 /// Ok(
426 /// Response::builder()
427 /// .status(StatusCode::NOT_FOUND)
428 /// .body(Body::from("NOT FOUND"))
429 /// .unwrap()
430 /// )
431 /// }
432 ///
433 /// # fn run() -> Router<Body, hyper::Error> {
434 /// let router = Router::builder()
435 /// .get("/home", home_handler)
436 /// .any(handler_404)
437 /// .build()
438 /// .unwrap();
439 /// # router
440 /// # }
441 /// # run();
442 /// ```
443 pub fn any<H, R>(self, handler: H) -> Self
444 where
445 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
446 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
447 {
448 self.add("/*", constants::ALL_POSSIBLE_HTTP_METHODS.to_vec(), handler)
449 }
450
451 /// Adds a new route with any method type and the handler at the specified path.
452 ///
453 /// # Examples
454 ///
455 /// ```
456 /// use routerify::Router;
457 /// use hyper::{Response, Request, Body};
458 ///
459 /// async fn home_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
460 /// Ok(Response::new(Body::from("home")))
461 /// }
462 ///
463 /// # fn run() -> Router<Body, hyper::Error> {
464 /// let router = Router::builder()
465 /// // It will accept requests at any method type at the specified path.
466 /// .any_method("/", home_handler)
467 /// .build()
468 /// .unwrap();
469 /// # router
470 /// # }
471 /// # run();
472 /// ```
473 pub fn any_method<H, R, P>(self, path: P, handler: H) -> Self
474 where
475 P: Into<String>,
476 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
477 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
478 {
479 self.add(path, constants::ALL_POSSIBLE_HTTP_METHODS.to_vec(), handler)
480 }
481
482 /// Adds a new route with the specified method(s) and the handler at the specified path. It can be used to define routes with multiple method types.
483 ///
484 /// # Examples
485 ///
486 /// ```
487 /// use routerify::Router;
488 /// use hyper::{Response, Request, Body, StatusCode, Method};
489 ///
490 /// async fn cart_checkout_handler(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
491 /// Ok(Response::new(Body::from("You shopping cart is being checking out")))
492 /// }
493 ///
494 /// # fn run() -> Router<Body, hyper::Error> {
495 /// let router = Router::builder()
496 /// .add("/checkout", vec![Method::GET, Method::POST], cart_checkout_handler)
497 /// .build()
498 /// .unwrap();
499 /// # router
500 /// # }
501 /// # run();
502 /// ```
503 pub fn add<P, H, R>(self, path: P, methods: Vec<Method>, handler: H) -> Self
504 where
505 P: Into<String>,
506 H: Fn(Request<hyper::Body>) -> R + Send + Sync + 'static,
507 R: Future<Output = Result<Response<B>, E>> + Send + 'static,
508 {
509 self.and_then(move |mut inner| {
510 let mut path = path.into();
511
512 if !path.ends_with('/') && !path.ends_with('*') {
513 path.push('/');
514 }
515
516 let route = Route::new(path, methods, handler)?;
517 inner.routes.push(route);
518
519 crate::Result::Ok(inner)
520 })
521 }
522
523 /// It mounts a router onto another router. It can be very useful when you want to write modular routing logic.
524 ///
525 /// # Examples
526 ///
527 /// ```
528 /// use routerify::Router;
529 /// use hyper::{Response, Request, Body};
530 ///
531 /// mod api {
532 /// use routerify::Router;
533 /// use hyper::{Response, Request, Body};
534 ///
535 /// pub fn router() -> Router<Body, hyper::Error> {
536 /// Router::builder()
537 /// .get("/users", |req| async move { Ok(Response::new(Body::from("User list"))) })
538 /// .get("/books", |req| async move { Ok(Response::new(Body::from("Book list"))) })
539 /// .build()
540 /// .unwrap()
541 /// }
542 /// }
543 ///
544 /// # fn run() -> Router<Body, hyper::Error> {
545 /// let router = Router::builder()
546 /// // Now, mount the api router at `/api` path.
547 /// .scope("/api", api::router())
548 /// .build()
549 /// .unwrap();
550 /// # router
551 /// # }
552 /// # run();
553 /// ```
554 ///
555 /// Now, the app can handle requests on: `/api/users` and `/api/books` paths.
556 pub fn scope<P>(self, path: P, mut router: Router<B, E>) -> Self
557 where
558 P: Into<String>,
559 {
560 let mut path = path.into();
561
562 if path.ends_with('/') {
563 path = (&path[..path.len() - 1]).to_string();
564 }
565
566 let mut builder = self;
567
568 for pre_middleware in router.pre_middlewares.iter_mut() {
569 let new_pre_middleware = PreMiddleware::new_with_boxed_handler(
570 format!("{}{}", path.as_str(), pre_middleware.path.as_str()),
571 pre_middleware
572 .handler
573 .take()
574 .expect("No handler found in one of the pre-middlewares"),
575 pre_middleware.scope_depth + 1,
576 );
577 builder = builder.and_then(move |mut inner| {
578 inner.pre_middlewares.push(new_pre_middleware?);
579 crate::Result::Ok(inner)
580 });
581 }
582
583 for route in router.routes.iter_mut() {
584 let new_route = Route::new_with_boxed_handler(
585 format!("{}{}", path.as_str(), route.path.as_str()),
586 route.methods.clone(),
587 route.handler.take().expect("No handler found in one of the routes"),
588 route.scope_depth + 1,
589 );
590 builder = builder.and_then(move |mut inner| {
591 inner.routes.push(new_route?);
592 crate::Result::Ok(inner)
593 });
594 }
595
596 for post_middleware in router.post_middlewares.iter_mut() {
597 let new_post_middleware = PostMiddleware::new_with_boxed_handler(
598 format!("{}{}", path.as_str(), post_middleware.path.as_str()),
599 post_middleware
600 .handler
601 .take()
602 .expect("No handler found in one of the post-middlewares"),
603 post_middleware.scope_depth + 1,
604 );
605 builder = builder.and_then(move |mut inner| {
606 inner.post_middlewares.push(new_post_middleware?);
607 crate::Result::Ok(inner)
608 });
609 }
610
611 for scoped_data_map in router.scoped_data_maps.iter_mut() {
612 let new_path = format!("{}{}", path.as_str(), scoped_data_map.path.as_str());
613 let data_map = Arc::try_unwrap(
614 scoped_data_map
615 .data_map
616 .take()
617 .expect("No data map found in one of the scoped data maps"),
618 )
619 .expect("Non-zero owner of the shared data map in one of the scoped data maps");
620
621 builder = builder.and_then(move |mut inner| {
622 let data_maps = &mut inner.data_maps;
623
624 let data_map_arr = data_maps.get_mut(&new_path);
625 if let Some(data_map_arr) = data_map_arr {
626 data_map_arr.push(data_map);
627 } else {
628 data_maps.insert(new_path, vec![data_map]);
629 }
630
631 crate::Result::Ok(inner)
632 });
633 }
634
635 builder
636 }
637}
638
639impl<B: HttpBody + Send + Sync + 'static, E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static>
640 RouterBuilder<B, E>
641{
642 /// Adds a single middleware. A pre middleware can be created by [`Middleware::pre`](./enum.Middleware.html#method.pre) method and a post
643 /// middleware can be created by [`Middleware::post`](./enum.Middleware.html#method.post) method.
644 ///
645 /// # Examples
646 ///
647 /// ```
648 /// use routerify::{Router, Middleware};
649 /// use hyper::{Response, Request, Body};
650 /// use std::convert::Infallible;
651 ///
652 /// # fn run() -> Router<Body, Infallible> {
653 /// let router = Router::builder()
654 /// // Create and attach a pre middleware.
655 /// .middleware(Middleware::pre(|req| async move { /* Do some operations */ Ok(req) }))
656 /// // Create and attach a post middleware.
657 /// .middleware(Middleware::post(|res| async move { /* Do some operations */ Ok(res) }))
658 /// .build()
659 /// .unwrap();
660 /// # router
661 /// # }
662 /// # run();
663 /// ```
664 pub fn middleware(self, m: Middleware<B, E>) -> Self {
665 self.and_then(move |mut inner| {
666 match m {
667 Middleware::Pre(middleware) => {
668 inner.pre_middlewares.push(middleware);
669 }
670 Middleware::Post(middleware) => {
671 inner.post_middlewares.push(middleware);
672 }
673 }
674 crate::Result::Ok(inner)
675 })
676 }
677
678 /// Specify app data to be shared across route handlers, middlewares and the error handler.
679 ///
680 /// Please refer to the [Data and State Sharing](./index.html#data-and-state-sharing) for more info.
681 pub fn data<T: Send + Sync + 'static>(self, data: T) -> Self {
682 self.and_then(move |mut inner| {
683 let data_maps = &mut inner.data_maps;
684
685 let data_map_arr = data_maps.get_mut(&"/*".to_owned());
686 if let Some(data_map_arr) = data_map_arr {
687 let first_data_map = data_map_arr.get_mut(0).unwrap();
688 first_data_map.insert(data);
689 } else {
690 let mut data_map = DataMap::new();
691 data_map.insert(data);
692 data_maps.insert("/*".to_owned(), vec![data_map]);
693 }
694
695 crate::Result::Ok(inner)
696 })
697 }
698
699 /// Adds a handler to handle any error raised by the routes or any middlewares. Please refer to [Error Handling](./index.html#error-handling) section
700 /// for more info.
701 pub fn err_handler<H, R>(self, handler: H) -> Self
702 where
703 H: Fn(crate::RouteError) -> R + Send + Sync + 'static,
704 R: Future<Output = Response<B>> + Send + 'static,
705 {
706 let handler: ErrHandlerWithoutInfo<B> = Box::new(move |err: crate::RouteError| Box::new(handler(err)));
707
708 self.and_then(move |mut inner| {
709 inner.err_handler = Some(ErrHandler::WithoutInfo(handler));
710 crate::Result::Ok(inner)
711 })
712 }
713
714 /// Adds a handler to handle any error raised by the routes or any middlewares.
715 ///
716 /// Here, the handler also access [request info](./struct.RequestInfo.html) e.g. headers, method, uri etc to generate response based on the request information.
717 ///
718 /// Please refer to [Error Handling](./index.html#error-handling) section
719 /// for more info.
720 pub fn err_handler_with_info<H, R>(self, handler: H) -> Self
721 where
722 H: Fn(crate::RouteError, RequestInfo) -> R + Send + Sync + 'static,
723 R: Future<Output = Response<B>> + Send + 'static,
724 {
725 let handler: ErrHandlerWithInfo<B> =
726 Box::new(move |err: crate::RouteError, req_info: RequestInfo| Box::new(handler(err, req_info)));
727
728 self.and_then(move |mut inner| {
729 inner.err_handler = Some(ErrHandler::WithInfo(handler));
730 crate::Result::Ok(inner)
731 })
732 }
733}
734
735impl<B: HttpBody + Send + Sync + 'static, E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static> Default
736 for RouterBuilder<B, E>
737{
738 fn default() -> RouterBuilder<B, E> {
739 RouterBuilder {
740 inner: Ok(BuilderInner {
741 pre_middlewares: Vec::new(),
742 routes: Vec::new(),
743 post_middlewares: Vec::new(),
744 data_maps: HashMap::new(),
745 err_handler: None,
746 }),
747 }
748 }
749}