routerify/
lib.rs

1//! `Routerify` provides a lightweight, idiomatic, composable and modular router implementation with middleware support for the Rust HTTP library [hyper](https://hyper.rs/).
2//!
3//! Routerify's core features:
4//!
5//! - 🌀 Design complex routing using [scopes](https://github.com/routerify/routerify/blob/master/examples/scoped_router.rs) and [middlewares](https://github.com/routerify/routerify/blob/master/examples/middleware.rs)
6//!
7//! - 🚀 Fast route matching using [`RegexSet`](https://docs.rs/regex/1.4.3/regex/struct.RegexSet.html)
8//!
9//! - 🍺 Route handlers may return any [HttpBody](https://docs.rs/hyper/0.14.4/hyper/body/trait.HttpBody.html)
10//!
11//! - ❗ Flexible [error handling](https://github.com/routerify/routerify/blob/master/examples/error_handling_with_request_info.rs) strategy
12//!
13//! - 💁 [`WebSocket` support](https://github.com/routerify/routerify-websocket) out of the box.
14//!
15//! - 🔥 Route handlers and middleware [may share state](https://github.com/routerify/routerify/blob/master/examples/share_data_and_state.rs)
16//!
17//! - 🍗 [Extensive documentation](https://docs.rs/routerify/) and [examples](https://github.com/routerify/routerify/tree/master/examples)
18//!
19//! To generate a quick server app using [Routerify](https://github.com/routerify/routerify) and [hyper](https://hyper.rs/),
20//! please check out [hyper-routerify-server-template](https://github.com/routerify/hyper-routerify-server-template).
21//!
22//!
23//! ## Benchmarks
24//!
25//! | Framework      | Language    | Requests/sec |
26//! |----------------|-------------|--------------|
27//! | [hyper v0.14](https://github.com/hyperium/hyper) | Rust 1.50.0 | 144,583 |
28//! | [routerify v2.0.0](https://github.com/routerify/routerify) with [hyper v0.14](https://github.com/hyperium/hyper) | Rust 1.50.0 | 144,621 |
29//! | [actix-web v3](https://github.com/actix/actix-web) | Rust 1.50.0 | 131,292 |
30//! | [warp v0.3](https://github.com/seanmonstar/warp) | Rust 1.50.0 | 145,362 |
31//! | [go-httprouter, branch master](https://github.com/julienschmidt/httprouter) | Go 1.16 | 130,662 |
32//! | [Rocket, branch master](https://github.com/SergioBenitez/Rocket) | Rust 1.50.0 | 130,045 |
33//!
34//! For more info, please visit [Benchmarks](https://github.com/routerify/routerify-benchmark).
35//!
36//! ## Basic Example
37//!
38//! A simple example using `Routerify` with `hyper` would look like the following:
39//!
40//! ```no_run
41//! use hyper::{Body, Request, Response, Server, StatusCode};
42//! // Import the routerify prelude traits.
43//! use routerify::prelude::*;
44//! use routerify::{Middleware, Router, RouterService, RequestInfo};
45//! use std::{convert::Infallible, net::SocketAddr};
46//!
47//! // Define an app state to share it across the route handlers and middlewares.
48//! struct State(u64);
49//!
50//! // A handler for "/" page.
51//! async fn home_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
52//!     // Access the app state.
53//!     let state = req.data::<State>().unwrap();
54//!     println!("State value: {}", state.0);
55//!
56//!     Ok(Response::new(Body::from("Home page")))
57//! }
58//!
59//! // A handler for "/users/:userId" page.
60//! async fn user_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
61//!     let user_id = req.param("userId").unwrap();
62//!     Ok(Response::new(Body::from(format!("Hello {}", user_id))))
63//! }
64//!
65//! // A middleware which logs an http request.
66//! async fn logger(req: Request<Body>) -> Result<Request<Body>, Infallible> {
67//!     println!("{} {} {}", req.remote_addr(), req.method(), req.uri().path());
68//!     Ok(req)
69//! }
70//!
71//! // Define an error handler function which will accept the `routerify::Error`
72//! // and the request information and generates an appropriate response.
73//! async fn error_handler(err: routerify::RouteError, _: RequestInfo) -> Response<Body> {
74//!     eprintln!("{}", err);
75//!     Response::builder()
76//!         .status(StatusCode::INTERNAL_SERVER_ERROR)
77//!         .body(Body::from(format!("Something went wrong: {}", err)))
78//!         .unwrap()
79//! }
80//!
81//! // Create a `Router<Body, Infallible>` for response body type `hyper::Body`
82//! // and for handler error type `Infallible`.
83//! fn router() -> Router<Body, Infallible> {
84//!     // Create a router and specify the logger middleware and the handlers.
85//!     // Here, "Middleware::pre" means we're adding a pre middleware which will be executed
86//!     // before any route handlers.
87//!     Router::builder()
88//!         // Specify the state data which will be available to every route handlers,
89//!         // error handler and middlewares.
90//!         .data(State(100))
91//!         .middleware(Middleware::pre(logger))
92//!         .get("/", home_handler)
93//!         .get("/users/:userId", user_handler)
94//!         .err_handler_with_info(error_handler)
95//!         .build()
96//!         .unwrap()
97//! }
98//!
99//! #[tokio::main]
100//! async fn main() {
101//!     let router = router();
102//!
103//!     // Create a Service from the router above to handle incoming requests.
104//!     let service = RouterService::new(router).unwrap();
105//!
106//!     // The address on which the server will be listening.
107//!     let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
108//!
109//!     // Create a server by passing the created service to `.serve` method.
110//!     let server = Server::bind(&addr).serve(service);
111//!
112//!     println!("App is running on: {}", addr);
113//!     if let Err(err) = server.await {
114//!         eprintln!("Server error: {}", err);
115//!    }
116//! }
117//! ```
118//!
119//! ## Routing
120//!
121//! ### Route Handlers
122//!
123//! A handler could be a function or a closure to handle a request at a specified route path.
124//!
125//! Here is a handler with a function:
126//!
127//! ```
128//! use routerify::Router;
129//! use hyper::{Response, Request, Body};
130//! use std::convert::Infallible;
131//!
132//! // A handler for "/about" page.
133//! async fn about_handler(_: Request<Body>) -> Result<Response<Body>, Infallible> {
134//!     Ok(Response::new(Body::from("About page")))
135//! }
136//!
137//! # fn run() -> Router<Body, Infallible> {
138//! let router = Router::builder()
139//!     .get("/about", about_handler)
140//!     .build()
141//!     .unwrap();
142//! # router
143//! # }
144//! # run();
145//! ```
146//!
147//! Here is a handler with closure function:
148//!
149//! ```
150//! use routerify::Router;
151//! use hyper::{Response, Body};
152//! # use std::convert::Infallible;
153//!
154//! # fn run() -> Router<Body, Infallible> {
155//! let router = Router::builder()
156//!     .get("/about", |req| async move { Ok(Response::new(Body::from("About page"))) })
157//!     .build()
158//!     .unwrap();
159//! # router
160//! # }
161//! # run();
162//! ```
163//!
164//! ### Route Paths
165//!
166//! Route paths, in combination with a request method, define the endpoints at which requests can be made.
167//! Route paths can be strings or strings with glob pattern `*`.
168//!
169//!
170//! Here are some examples:
171//!
172//! This route path will match with exactly "/about":
173//!
174//! ```
175//! use routerify::Router;
176//! use hyper::{Response, Body};
177//! # use std::convert::Infallible;
178//!
179//! # fn run() -> Router<Body, Infallible> {
180//! let router = Router::builder()
181//!     .get("/about", |req| async move { Ok(Response::new(Body::from("About page"))) })
182//!     .build()
183//!     .unwrap();
184//! # router
185//! # }
186//! # run();
187//! ```
188//!
189//! A route path using the glob `*` pattern:
190//!
191//! ```
192//! use routerify::Router;
193//! use hyper::{Response, Body};
194//! # use std::convert::Infallible;
195//!
196//! # fn run() -> Router<Body, Infallible> {
197//! let router = Router::builder()
198//!     .get("/users/*", |req| async move { Ok(Response::new(Body::from("It will match /users/, /users/any_path"))) })
199//!     .build()
200//!     .unwrap();
201//! # router
202//! # }
203//! # run();
204//! ```
205//!
206//! #### Handle 404 Pages
207//!
208//! Here is an example to handle 404 pages.
209//!
210//! ```
211//! use routerify::Router;
212//! use hyper::{Response, Body, StatusCode};
213//! # use std::convert::Infallible;
214//!
215//! # fn run() -> Router<Body, Infallible> {
216//! let router = Router::builder()
217//!     .get("/users", |req| async move { Ok(Response::new(Body::from("User List"))) })
218//!     // It fallbacks to the following route for any non-existent routes.
219//!     .any(|_req| async move {
220//!         Ok(
221//!             Response::builder()
222//!             .status(StatusCode::NOT_FOUND)
223//!             .body(Body::from("NOT FOUND"))
224//!             .unwrap()
225//!         )
226//!     })
227//!     .build()
228//!     .unwrap();
229//! # router
230//! # }
231//! # run();
232//! ```
233//!
234//! ### Route Parameters
235//!
236//! Route parameters are named URL segments that are used to capture the values specified at their position in the URL.
237//! The captured values can be accessed by `req.params` and `re.param` methods using the name of the route parameter specified in the path.
238//!
239//! ```txt
240//! Route path: /users/:userName/books/:bookName
241//! Request URL: http://localhost:3000/users/alice/books/HarryPotter
242//! req.params() returns a hashmap: { "userName": "alice", "bookName": "HarryPotter" }
243//! ```
244//!
245//! To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.
246//!
247//! ```
248//! use routerify::Router;
249//! // Add routerify prelude traits.
250//! use routerify::prelude::*;
251//! use hyper::{Response, Body};
252//! # use std::convert::Infallible;
253//!
254//! # fn run() -> Router<Body, Infallible> {
255//! let router = Router::builder()
256//!     .get("/users/:userName/books/:bookName", |req| async move {
257//!         let user_name = req.param("userName").unwrap();
258//!         let book_name = req.param("bookName").unwrap();
259//!
260//!         Ok(Response::new(Body::from(format!("Username: {}, Book Name: {}", user_name, book_name))))
261//!      })
262//!      .build()
263//!      .unwrap();
264//! # router
265//! # }
266//! # run();
267//! ```
268//!
269//! ### Scoping/Mounting Router
270//!
271//! The `routerify::Router` is a modular, lightweight and mountable router component. A router can be scoped in or mount to a
272//! different router.
273//!
274//! Here is a simple example which creates a Router and it mounts that router at `/api` path with `.scope()` method:
275//!
276//! ```
277//! use routerify::Router;
278//! use routerify::prelude::*;
279//! use hyper::{Response, Body};
280//! use std::convert::Infallible;
281//!
282//! fn api_router() -> Router<Body, Infallible> {
283//!     Router::builder()
284//!         .get("/books", |req| async move { Ok(Response::new(Body::from("List of books"))) })
285//!         .get("/books/:bookId", |req| async move {
286//!             Ok(Response::new(Body::from(format!("Show book: {}", req.param("bookId").unwrap()))))
287//!          })
288//!         .build()
289//!         .unwrap()
290//! }
291//!
292//! # fn run() -> Router<Body, Infallible> {
293//! let router = Router::builder()
294//!      // Mounts the API router at "/api" path .
295//!      .scope("/api", api_router())
296//!      .build()
297//!      .unwrap();
298//! # router
299//! # }
300//! # run();
301//! ```
302//! Now, the app can handle requests to `/api/books` as well as to `/api/books/:bookId`.
303//!
304//! ## Middleware
305//!
306//! The `Routerify` also supports Middleware functionality. If you are unfamiliar with Middleware, in short, here a middlewar is a function (or could be a closure
307//! function) which access the `req` and `res` object and does some changes to them and passes the transformed request and response object to the other middlewares and the actual route handler
308//! to process it.
309//!
310//! A Middleware function can do the following tasks:
311//!
312//! - Execute any code.
313//! - Transform the request and the response object.
314//!
315//! Here, the `Routerify` categorizes the middlewares into two different types:
316//!
317//! ### Pre Middleware
318//!
319//! The pre Middlewares will be executed before any route handlers and it will access the `req` object and it can also do some changes to the request object
320//! if required.
321//!
322//! Here is an example of a pre middleware:
323//!
324//! ```
325//! use routerify::{Router, Middleware};
326//! use hyper::{Request, Body};
327//! use std::convert::Infallible;
328//!
329//! // The handler for a pre middleware.
330//! // It accepts a `req` and it transforms the `req` and passes it to the next middlewares.
331//! async fn my_pre_middleware_handler(req: Request<Body>) -> Result<Request<Body>, Infallible> {
332//!     // Do some changes if required.
333//!     let transformed_req = req;
334//!
335//!     // Then return the transformed request object to be consumed by the other middlewares
336//!     // and the route handlers.
337//!     Ok(transformed_req)
338//! }
339//!
340//! # fn run() -> Router<Body, Infallible> {
341//! let router = Router::builder()
342//!      // Create a pre middleware instance by `Middleware::pre` method
343//!      // and attach it.
344//!      .middleware(Middleware::pre(my_pre_middleware_handler))
345//!      // A middleware can also be attached on a specific path as shown below.
346//!      .middleware(Middleware::pre_with_path("/my-path/log", my_pre_middleware_handler).unwrap())
347//!      .build()
348//!      .unwrap();
349//! # router
350//! # }
351//! # run();
352//! ```
353//!
354//! Here is a pre middleware which logs the incoming requests:
355//!
356//! ```
357//! use routerify::{Router, Middleware};
358//! use routerify::prelude::*;
359//! use hyper::{Request, Body};
360//! use std::convert::Infallible;
361//!
362//! async fn logger_middleware_handler(req: Request<Body>) -> Result<Request<Body>, Infallible> {
363//!     println!("{} {} {}", req.remote_addr(), req.method(), req.uri().path());
364//!     Ok(req)
365//! }
366//!
367//! # fn run() -> Router<Body, Infallible> {
368//! let router = Router::builder()
369//!      .middleware(Middleware::pre(logger_middleware_handler))
370//!      .build()
371//!      .unwrap();
372//! # router
373//! # }
374//! # run();
375//! ```
376//!
377//! ### Post Middleware
378//!
379//! The post Middlewares will be executed after all the route handlers process the request and generates a response and it will access that response object and the request info(optional)
380//! and it can also do some changes to the response if required.
381//!
382//! Here is an example of a post middleware:
383//!
384//! ```
385//! use routerify::{Router, Middleware};
386//! use hyper::{Response, Body};
387//! use std::convert::Infallible;
388//!
389//! // The handler for a post middleware.
390//! // It accepts a `res` and it transforms the `res` and passes it to the next middlewares.
391//! async fn my_post_middleware_handler(res: Response<Body>) -> Result<Response<Body>, Infallible> {
392//!     // Do some changes if required.
393//!     let transformed_res = res;
394//!
395//!     // Then return the transformed response object to be consumed by the other middlewares.
396//!     Ok(transformed_res)
397//! }
398//!
399//! # fn run() -> Router<Body, Infallible> {
400//! let router = Router::builder()
401//!      // Create a post middleware instance by `Middleware::post` method
402//!      // and attach it.
403//!      .middleware(Middleware::post(my_post_middleware_handler))
404//!      // A middleware can also be attached on a specific path as shown below.
405//!      .middleware(Middleware::post_with_path("/my-path/log", my_post_middleware_handler).unwrap())
406//!      .build()
407//!      .unwrap();
408//! # router
409//! # }
410//! # run();
411//! ```
412//!
413//! Here is a post middleware which adds a header to the response object:
414//!
415//! ```
416//! use routerify::{Router, Middleware};
417//! use routerify::prelude::*;
418//! use hyper::{Response, Body, header::HeaderValue};
419//! use std::convert::Infallible;
420//!
421//! async fn my_post_middleware_handler(mut res: Response<Body>) -> Result<Response<Body>, Infallible> {
422//!     // Add a header to response object.
423//!     res.headers_mut().insert("x-my-custom-header", HeaderValue::from_static("my-value"));
424//!
425//!     Ok(res)
426//! }
427//!
428//! # fn run() -> Router<Body, Infallible> {
429//! let router = Router::builder()
430//!      .middleware(Middleware::post(my_post_middleware_handler))
431//!      .build()
432//!      .unwrap();
433//! # router
434//! # }
435//! # run();
436//! ```
437//!
438//! #### Post Middleware with Request Info
439//!
440//! Sometimes, the post middleware requires the request informations e.g. headers, method, uri etc to generate a new response. As an example, it could be used to manage
441//! sessions. To register this kind of post middleware, you have to use [`Middleware::post_with_info`](./enum.Middleware.html#method.post_with_info) method as follows:
442//!
443//! ```
444//! use routerify::{Router, Middleware, RequestInfo};
445//! use hyper::{Response, Body};
446//! use std::convert::Infallible;
447//!
448//! // The handler for a post middleware which requires request info.
449//! // It accepts `res` and `req_info` and it transforms the `res` and passes it to the next middlewares.
450//! async fn post_middleware_with_info_handler(res: Response<Body>, req_info: RequestInfo) -> Result<Response<Body>, Infallible> {
451//!     let transformed_res = res;
452//!
453//!     // Do some response transformation based on the request headers, method etc.
454//!     let _headers = req_info.headers();
455//!
456//!     // Then return the transformed response object to be consumed by the other middlewares.
457//!     Ok(transformed_res)
458//! }
459//!
460//! # fn run() -> Router<Body, Infallible> {
461//! let router = Router::builder()
462//!      // Create a post middleware instance by `Middleware::post_with_info` method
463//!      // and attach it.
464//!      .middleware(Middleware::post_with_info(post_middleware_with_info_handler))
465//!      // This middleware can also be attached on a specific path as shown below.
466//!      .middleware(Middleware::post_with_info_with_path("/my-path", post_middleware_with_info_handler).unwrap())
467//!      .build()
468//!      .unwrap();
469//! # router
470//! # }
471//! # run();
472//! ```
473//!
474//! ### The built-in Middleware
475//!
476//! Here is a list of some middlewares which are published in different crates:
477//!
478//! - [routerify-cors](https://github.com/routerify/routerify-cors): A post middleware which enables `CORS` to the routes.
479//! - [routerify-query](https://github.com/routerify/routerify-query): A pre middleware which parses the request query string.
480//!
481//! ## Data and State Sharing
482//!
483//! `Routerify` also allows you to share data or app state across the route handlers, middlewares and the error handler via the [`RouterBuilder`](./struct.RouterBuilder.html) method
484//! [`data`](./struct.RouterBuilder.html#method.data). As it provides composable router API, it also allows to have app state/data per each sub-router.
485//!
486//! Here is an example to share app state:
487//!
488//! ```
489//! # use hyper::{Body, Request, Response, Server, StatusCode};
490//! // Import the routerify prelude traits.
491//! use routerify::prelude::*;
492//! use routerify::{Middleware, Router, RouterService, RequestInfo};
493//! # use std::{convert::Infallible, net::SocketAddr};
494//!
495//! // Define an app state to share it across the route handlers, middlewares
496//! // and the error handler.
497//! struct State(u64);
498//!
499//! // A handler for "/" page.
500//! async fn home_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
501//!     // Access the app state.
502//!     let state = req.data::<State>().unwrap();
503//!     println!("State value: {}", state.0);
504//!
505//!     Ok(Response::new(Body::from("Home page")))
506//! }
507//!
508//! // A middleware which logs an http request.
509//! async fn logger(req: Request<Body>) -> Result<Request<Body>, Infallible> {
510//!     // You can also access the same state from middleware.
511//!     let state = req.data::<State>().unwrap();
512//!     println!("State value: {}", state.0);
513//!
514//!     println!("{} {} {}", req.remote_addr(), req.method(), req.uri().path());
515//!     Ok(req)
516//! }
517//!
518//! // Define an error handler function which will accept the `routerify::Error`
519//! // and the request information and generates an appropriate response.
520//! async fn error_handler(err: routerify::RouteError, req_info: RequestInfo) -> Response<Body> {
521//!     // You can also access the same state from error handler.
522//!     let state = req_info.data::<State>().unwrap();
523//!     println!("State value: {}", state.0);
524//!
525//!     eprintln!("{}", err);
526//!     Response::builder()
527//!         .status(StatusCode::INTERNAL_SERVER_ERROR)
528//!         .body(Body::from(format!("Something went wrong: {}", err)))
529//!         .unwrap()
530//! }
531//!
532//! // Create a `Router<Body, Infallible>` for response body type `hyper::Body`
533//! // and for handler error type `Infallible`.
534//! fn router() -> Router<Body, Infallible> {
535//!     Router::builder()
536//!         // Specify the state data which will be available to every route handlers,
537//!         // error handler and middlewares.
538//!         .data(State(100))
539//!         .middleware(Middleware::pre(logger))
540//!         .get("/", home_handler)
541//!         .err_handler_with_info(error_handler)
542//!         .build()
543//!         .unwrap()
544//! }
545//!
546//! # #[tokio::main]
547//! # async fn run() {
548//! #    let router = router();
549//! #
550//! #    // Create a Service from the router above to handle incoming requests.
551//! #    let service = RouterService::new(router).unwrap();
552//! #
553//! #   // The address on which the server will be listening.
554//! #   let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
555//! #
556//! #   // Create a server by passing the created service to `.serve` method.
557//! #   let server = Server::bind(&addr).serve(service);
558//! #
559//! #   println!("App is running on: {}", addr);
560//! #   if let Err(err) = server.await {
561//! #       eprintln!("Server error: {}", err);
562//! #  }
563//! # }
564//! ```
565//!
566//! Here is an example to `mutate` app state:
567//!
568//! ```
569//! # use hyper::{Body, Request, Response, Server, StatusCode};
570//! // Import the routerify prelude traits.
571//! use routerify::prelude::*;
572//! use routerify::{Middleware, Router, RouterService, RequestInfo};
573//! # use std::{convert::Infallible, net::SocketAddr};
574//! use std::sync::Mutex;
575//!
576//! // Define an app state to share it across the route handlers, middlewares
577//! // and the error handler.
578//! struct State(u64);
579//!
580//! // A handler for "/" page.
581//! async fn home_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
582//!     // Access the app state.
583//!     let state = req.data::<Mutex<State>>().unwrap();
584//!     let mut lock = state.lock().unwrap();
585//!     // Mutate the app state if needed.
586//!     lock.0 += 1;
587//!
588//!     println!("Updated State value: {}", lock.0);
589//!
590//!     Ok(Response::new(Body::from("Home page")))
591//! }
592//!
593//! // Create a `Router<Body, Infallible>` for response body type `hyper::Body`
594//! // and for handler error type `Infallible`.
595//! fn router() -> Router<Body, Infallible> {
596//!     Router::builder()
597//!         // Specify the state data which will be available to every route handlers,
598//!         // error handler and middlewares.
599//!         .data(Mutex::new(State(100)))
600//!         .get("/", home_handler)
601//!         .build()
602//!         .unwrap()
603//! }
604//!
605//! # #[tokio::main]
606//! # async fn run() {
607//! #    let router = router();
608//! #
609//! #    // Create a Service from the router above to handle incoming requests.
610//! #    let service = RouterService::new(router).unwrap();
611//! #
612//! #   // The address on which the server will be listening.
613//! #   let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
614//! #
615//! #   // Create a server by passing the created service to `.serve` method.
616//! #   let server = Server::bind(&addr).serve(service);
617//! #
618//! #   println!("App is running on: {}", addr);
619//! #   if let Err(err) = server.await {
620//! #       eprintln!("Server error: {}", err);
621//! #  }
622//! # }
623//! ```
624//!
625//! Here is any example on having app state per each sub-router:
626//!
627//! ```
628//! # use hyper::{Body, Request, Response, Server, StatusCode};
629//! # // Import the routerify prelude traits.
630//! # use routerify::prelude::*;
631//! # use routerify::{Middleware, Router, RouterService, RequestInfo};
632//! # use std::{convert::Infallible, net::SocketAddr};
633//!
634//! mod foo {
635//!     # use std::{convert::Infallible, net::SocketAddr};
636//!     # use routerify::{Middleware, Router, RouterService, RequestInfo};
637//!     # use hyper::{Body, Request, Response, Server, StatusCode};
638//!     pub fn router() -> Router<Body, Infallible> {
639//!         Router::builder()
640//!             // Specify data for this sub-router only.
641//!             .data("Data for foo router")
642//!             .build()
643//!             .unwrap()
644//!     }
645//! }
646//!
647//! mod bar {
648//!     # use std::{convert::Infallible, net::SocketAddr};
649//!     # use routerify::{Middleware, Router, RouterService, RequestInfo};
650//!     # use hyper::{Body, Request, Response, Server, StatusCode};
651//!     pub fn router() -> Router<Body, Infallible> {
652//!         Router::builder()
653//!             // Specify data for this sub-router only.
654//!             .data("Data for bar router")
655//!             .build()
656//!             .unwrap()
657//!     }
658//! }
659//!
660//! fn router() -> Router<Body, Infallible> {
661//!     Router::builder()
662//!         // This data will be available to all the child sub-routers.
663//!         .data(100_u32)
664//!         .scope("/foo", foo::router())
665//!         .scope("/bar", bar::router())
666//!         .build()
667//!         .unwrap()
668//! }
669//! ```
670//!
671//! You can also share multiple data as follows:
672//!
673//! ```
674//! # use hyper::{Body, Request, Response, Server, StatusCode};
675//! # // Import the routerify prelude traits.
676//! # use routerify::prelude::*;
677//! # use routerify::{Middleware, Router, RouterService, RequestInfo};
678//! # use std::{convert::Infallible, net::SocketAddr};
679//! # use std::sync::Mutex;
680//! fn router() -> Router<Body, Infallible> {
681//!     Router::builder()
682//!         // Share multiple data, a single data for each data type.
683//!         .data(100_u32)
684//!         .data(String::from("Hello world"))
685//!         .build()
686//!         .unwrap()
687//! }
688//! ```
689//!
690//! ### Request context
691//!
692//! It's possible to share data local to the request across the route handlers and middleware via the
693//! [`RequestExt`](./ext/trait.RequestExt.html) methods [`context`](./ext/trait.RequestExt.html#method.context)
694//! and [`set_context`](./ext/trait.RequestExt.html#method.set_context). In the error handler it can be accessed
695//! via [`RequestInfo`](./struct.RequestInfo.html) method [`context`](./struct.RequestInfo.html#method.context).
696//!
697//! ## Error Handling
698//!
699//! Any route or middleware could go wrong and throw an error. `Routerify` tries to add a default error handler in some cases. But, it also
700//! allows to attach a custom error handler. The error handler generates a response based on the error and the request info (optional).
701//!
702//! Routes and middleware may return any error type. The type must be the same for all routes, middleware and a router instance.
703//! The error is boxed into [`RouteError`](./type.RouteError.html)
704//! and propagated into an error handler. There, the original error is accessible after downcasting.
705//! See this [example](https://github.com/routerify/routerify/tree/master/examples/error_handling_with_custom_errors.rs)
706//! for handling custom errors.
707//!
708//! Here is an basic example:
709//!
710//! ```
711//! use routerify::{Router, Middleware};
712//! use routerify::prelude::*;
713//! use hyper::{Response, Body, StatusCode};
714//!
715//! // The error handler will accept the thrown error in routerify::Error type and
716//! // it will have to generate a response based on the error.
717//! async fn error_handler(err: routerify::RouteError) -> Response<Body> {
718//!     Response::builder()
719//!       .status(StatusCode::INTERNAL_SERVER_ERROR)
720//!       .body(Body::from("Something went wrong"))
721//!       .unwrap()
722//! }
723//!
724//! # fn run() -> Router<Body, hyper::Error> {
725//! let router = Router::builder()
726//!      .get("/users", |req| async move { Ok(Response::new(Body::from("It might raise an error"))) })
727//!      // Here attach the custom error handler defined above.
728//!      .err_handler(error_handler)
729//!      .build()
730//!      .unwrap();
731//! # router
732//! # }
733//! # run();
734//! ```
735//!
736//! ### Error Handling with Request Info
737//!
738//! Sometimes, it's needed to to generate response on error based on the request headers, method, uri etc. `Routerify` also provides a method [`err_handler_with_info`](./struct.RouterBuilder.html#method.err_handler_with_info)
739//! to register this kind of error handler as follows:
740//!
741//! ```
742//! use routerify::{Router, Middleware, RequestInfo};
743//! use routerify::prelude::*;
744//! use hyper::{Response, Body, StatusCode};
745//!
746//! // The error handler will accept the thrown error and the request info and
747//! // it will generate a response.
748//! async fn error_handler(err: routerify::RouteError, req_info: RequestInfo) -> Response<Body> {
749//!     // Now generate response based on the `err` and the `req_info`.
750//!     Response::builder()
751//!       .status(StatusCode::INTERNAL_SERVER_ERROR)
752//!       .body(Body::from("Something went wrong"))
753//!       .unwrap()
754//! }
755//!
756//! # fn run() -> Router<Body, hyper::Error> {
757//! let router = Router::builder()
758//!      .get("/users", |req| async move { Ok(Response::new(Body::from("It might raise an error"))) })
759//!      // Now register this error handler.
760//!      .err_handler_with_info(error_handler)
761//!      .build()
762//!      .unwrap();
763//! # router
764//! # }
765//! # run();
766//! ```
767
768pub use self::error::{Error, RouteError};
769pub use self::middleware::{Middleware, PostMiddleware, PreMiddleware};
770pub use self::route::Route;
771pub use self::router::{Router, RouterBuilder};
772#[doc(hidden)]
773pub use self::service::RequestService;
774pub use self::service::RequestServiceBuilder;
775pub use self::service::RouterService;
776pub use self::types::{RequestInfo, RouteParams};
777
778mod constants;
779mod data_map;
780mod error;
781pub mod ext;
782mod helpers;
783mod middleware;
784pub mod prelude;
785mod regex_generator;
786mod route;
787mod router;
788mod service;
789mod types;
790
791/// A Result type often returned from methods that can have routerify errors.
792pub type Result<T> = std::result::Result<T, RouteError>;