From 8411b7873680d4b5a2d390bdd2f520186bb94c9c Mon Sep 17 00:00:00 2001 From: Nylonicious <50183564+nylonicious@users.noreply.github.com> Date: Fri, 31 Dec 2021 16:16:33 +0100 Subject: [PATCH] Document calling extractors in FromRequest impl (#679) * Document calling extractors in FromRequest impl * Fix typo * Apply suggested changes --- axum/src/docs/extract.md | 59 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/axum/src/docs/extract.md b/axum/src/docs/extract.md index 6b0c17d2..feef409f 100644 --- a/axum/src/docs/extract.md +++ b/axum/src/docs/extract.md @@ -397,6 +397,65 @@ let app = Router::new().route("/foo", get(handler)); # }; ``` +# Accessing other extractors in [`FromRequest`] implementations + +When defining custom extractors you often need to access another extractors +in your implementation. + +```rust +use axum::{ + async_trait, + extract::{Extension, FromRequest, RequestParts, TypedHeader}, + headers::{authorization::Bearer, Authorization}, + http::StatusCode, + response::{IntoResponse, Response}, + routing::get, + AddExtensionLayer, Router, +}; + +#[derive(Clone)] +struct State { + // ... +} + +struct AuthenticatedUser { + // ... +} + +#[async_trait] +impl FromRequest for AuthenticatedUser +where + B: Send, +{ + type Rejection = Response; + + async fn from_request(req: &mut RequestParts) -> Result { + let TypedHeader(Authorization(token)) = + TypedHeader::>::from_request(req) + .await + .map_err(|err| err.into_response())?; + + let Extension(state): Extension = Extension::from_request(req) + .await + .map_err(|err| err.into_response())?; + + // actually perform the authorization... + unimplemented!() + } +} + +async fn handler(user: AuthenticatedUser) { + // ... +} + +let state = State { /* ... */ }; + +let app = Router::new().route("/", get(handler)).layer(AddExtensionLayer::new(state)); +# 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