Improve extractor docs (#327)

* Improve extractor docs

- Moves things from the `extract` module docs to the root module docs to
  make them more discoverable
- Adds section showing commonly used extractors
- More clarity around multiple extractors that mutate the request

* english...
This commit is contained in:
David Pedersen
2021-09-18 19:09:53 +02:00
committed by GitHub
parent 0c18caa10f
commit 593e3e319a
2 changed files with 171 additions and 149 deletions
+3 -124
View File
@@ -9,7 +9,7 @@
//!
//! ```rust,no_run
//! use axum::{
//! Json,
//! extract::Json,
//! handler::{post, Handler},
//! Router,
//! };
@@ -21,9 +21,7 @@
//! password: String,
//! }
//!
//! async fn create_user(payload: Json<CreateUser>) {
//! let payload: CreateUser = payload.0;
//!
//! async fn create_user(Json(payload): Json<CreateUser>) {
//! // ...
//! }
//!
@@ -66,38 +64,7 @@
//! }
//! }
//!
//! async fn handler(user_agent: ExtractUserAgent) {
//! let user_agent: HeaderValue = user_agent.0;
//!
//! // ...
//! }
//!
//! let app = Router::new().route("/foo", get(handler));
//! # async {
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
//! # };
//! ```
//!
//! # Multiple extractors
//!
//! Handlers can also contain multiple extractors:
//!
//! ```rust,no_run
//! use axum::{
//! extract::{Path, Query},
//! handler::get,
//! Router,
//! };
//! use std::collections::HashMap;
//!
//! async fn handler(
//! // Extract captured parameters from the URL
//! params: Path<HashMap<String, String>>,
//! // Parse query string into a `HashMap`
//! query_params: Query<HashMap<String, String>>,
//! // Buffer the request body into a `Bytes`
//! bytes: bytes::Bytes,
//! ) {
//! async fn handler(ExtractUserAgent(user_agent): ExtractUserAgent) {
//! // ...
//! }
//!
@@ -110,94 +77,6 @@
//! Note that only one extractor can consume the request body. If multiple body extractors are
//! applied a `500 Internal Server Error` response will be returned.
//!
//! # Optional extractors
//!
//! Wrapping extractors in `Option` will make them optional:
//!
//! ```rust,no_run
//! use axum::{
//! extract::Json,
//! handler::post,
//! Router,
//! };
//! use serde_json::Value;
//!
//! async fn create_user(payload: Option<Json<Value>>) {
//! if let Some(payload) = payload {
//! // We got a valid JSON payload
//! } else {
//! // Payload wasn't valid JSON
//! }
//! }
//!
//! let app = Router::new().route("/users", post(create_user));
//! # async {
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
//! # };
//! ```
//!
//! Wrapping extractors in `Result` makes them optional and gives you the reason
//! the extraction failed:
//!
//! ```rust,no_run
//! use axum::{
//! extract::{Json, rejection::JsonRejection},
//! handler::post,
//! Router,
//! };
//! use serde_json::Value;
//!
//! async fn create_user(payload: Result<Json<Value>, JsonRejection>) {
//! match payload {
//! Ok(payload) => {
//! // We got a valid JSON payload
//! }
//! Err(JsonRejection::MissingJsonContentType(_)) => {
//! // Request didn't have `Content-Type: application/json`
//! // header
//! }
//! Err(JsonRejection::InvalidJsonBody(_)) => {
//! // Couldn't deserialize the body into the target type
//! }
//! Err(JsonRejection::BodyAlreadyExtracted(_)) => {
//! // Another extractor had already consumed the body
//! }
//! Err(_) => {
//! // `JsonRejection` is marked `#[non_exhaustive]` so match must
//! // include a catch-all case.
//! }
//! }
//! }
//!
//! let app = Router::new().route("/users", post(create_user));
//! # async {
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
//! # };
//! ```
//!
//! # Reducing boilerplate
//!
//! If you're feeling adventurous you can even deconstruct the extractors
//! directly on the function signature:
//!
//! ```rust,no_run
//! use axum::{
//! extract::Json,
//! handler::post,
//! Router,
//! };
//! use serde_json::Value;
//!
//! async fn create_user(Json(value): Json<Value>) {
//! // `value` is of type `Value`
//! }
//!
//! let app = Router::new().route("/users", post(create_user));
//! # async {
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
//! # };
//! ```
//!
//! # Request body extractors
//!
//! Most of the time your request body type will be [`body::Body`] (a re-export