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>;