Improve documentation for router (#71)

Fixes #67
This commit is contained in:
David Pedersen 2021-08-01 15:42:50 +02:00 committed by GitHub
parent f581e3efb2
commit 6f30d4aa6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 1 deletions

View file

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement `Deref` most extractors ([#56](https://github.com/tokio-rs/axum/pull/56))
- Return `405 Method Not Allowed` for unsupported method for route ([#63](https://github.com/tokio-rs/axum/pull/63))
- Add extractor for remote connection info ([#55](https://github.com/tokio-rs/axum/pull/55))
- Improve documentation for routing ([#71](https://github.com/tokio-rs/axum/pull/71))
- Clarify required response body type when routing to `tower::Service`s ([#69](https://github.com/tokio-rs/axum/pull/69))
- Add `axum::body::box_body` to converting an `http_body::Body` to `axum::body::BoxBody` ([#69](https://github.com/tokio-rs/axum/pull/69))

View file

@ -6,6 +6,8 @@
//! - [Compatibility](#compatibility)
//! - [Handlers](#handlers)
//! - [Routing](#routing)
//! - [Precedence](#precedence)
//! - [Matching multiple methods](#matching-multiple-methods)
//! - [Extractors](#extractors)
//! - [Building responses](#building-responses)
//! - [Applying middleware](#applying-middleware)
@ -122,7 +124,92 @@
//! # };
//! ```
//!
//! Routes can also be dynamic like `/users/:id`.
//! Routes can also be dynamic like `/users/:id`. See [extractors](#extractors)
//! for more details.
//!
//! ## Precedence
//!
//! Note that routes are matched _bottom to top_ so routes that should have
//! higher precedence should be added _after_ routes with lower precedence:
//!
//! ```rust
//! use axum::{prelude::*, body::BoxBody};
//! use tower::{Service, ServiceExt, BoxError};
//! use http::{Method, Response, StatusCode};
//! use std::convert::Infallible;
//!
//! # #[tokio::main]
//! # async fn main() {
//! // `/foo` also matches `/:key` so adding the routes in this order means `/foo`
//! // will be inaccessible.
//! let mut app = route("/foo", get(|| async { "/foo called" }))
//! .route("/:key", get(|| async { "/:key called" }));
//!
//! // Even though we use `/foo` as the request URI, `/:key` takes precedence
//! // since its defined last.
//! let (status, body) = call_service(&mut app, Method::GET, "/foo").await;
//! assert_eq!(status, StatusCode::OK);
//! assert_eq!(body, "/:key called");
//!
//! // We have to add `/foo` after `/:key` since routes are matched bottom to
//! // top.
//! let mut new_app = route("/:key", get(|| async { "/:key called" }))
//! .route("/foo", get(|| async { "/foo called" }));
//!
//! // Now it works
//! let (status, body) = call_service(&mut new_app, Method::GET, "/foo").await;
//! assert_eq!(status, StatusCode::OK);
//! assert_eq!(body, "/foo called");
//!
//! // And the other route works as well
//! let (status, body) = call_service(&mut new_app, Method::GET, "/bar").await;
//! assert_eq!(status, StatusCode::OK);
//! assert_eq!(body, "/:key called");
//!
//! // Little helper function to make calling a service easier. Just for
//! // demonstration purposes.
//! async fn call_service<S>(
//! svc: &mut S,
//! method: Method,
//! uri: &str,
//! ) -> (StatusCode, String)
//! where
//! S: Service<Request<Body>, Response = Response<BoxBody>, Error = Infallible>
//! {
//! let req = Request::builder().method(method).uri(uri).body(Body::empty()).unwrap();
//! let res = svc.ready().await.unwrap().call(req).await.unwrap();
//!
//! let status = res.status();
//!
//! let body = res.into_body();
//! let body = hyper::body::to_bytes(body).await.unwrap();
//! let body = String::from_utf8(body.to_vec()).unwrap();
//!
//! (status, body)
//! }
//! # }
//! ```
//!
//! ## Matching multiple methods
//!
//! If you want a path to accept multiple HTTP methods you must add them all at
//! once:
//!
//! ```rust,no_run
//! use axum::prelude::*;
//!
//! // `GET /` and `POST /` are both accepted
//! let app = route("/", get(handler).post(handler));
//!
//! // This will _not_ work. Only `POST /` will be accessible.
//! let wont_work = route("/", get(handler)).route("/", post(handler));
//!
//! async fn handler() {}
//! # async {
//! # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
//! # hyper::Server::bind(&"".parse().unwrap()).serve(wont_work.into_make_service()).await.unwrap();
//! # };
//! ```
//!
//! # Extractors
//!