From 0517d92cb30449a8b84562c578d11911eeef4657 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Sat, 2 Jul 2022 11:44:17 +0200 Subject: [PATCH] Document running extractors from middleware (#1140) Fixes #1134 --- axum/src/docs/extract.md | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/axum/src/docs/extract.md b/axum/src/docs/extract.md index eedf5ec584..92784a65e5 100644 --- a/axum/src/docs/extract.md +++ b/axum/src/docs/extract.md @@ -12,6 +12,7 @@ Types and traits for extracting data from requests. - [Defining custom extractors](#defining-custom-extractors) - [Accessing other extractors in `FromRequest` implementations](#accessing-other-extractors-in-fromrequest-implementations) - [Request body extractors](#request-body-extractors) +- [Running extractors from middleware](#running-extractors-from-middleware) # Intro @@ -579,6 +580,62 @@ let app = Router::new() # }; ``` +# Running extractors from middleware + +Extractors can also be run from middleware by making a [`RequestParts`] and +running your extractor: + +```rust +use axum::{ + Router, + middleware::{self, Next}, + extract::{RequestParts, TypedHeader}, + http::{Request, StatusCode}, + response::Response, + headers::authorization::{Authorization, Bearer}, +}; + +async fn auth_middleware( + request: Request, + next: Next, +) -> Result +where + B: Send, +{ + // running extractors requires a `RequestParts` + let mut request_parts = RequestParts::new(request); + + // `TypedHeader>` extracts the auth token but + // `RequestParts::extract` works with anything that implements `FromRequest` + let auth = request_parts.extract::>>() + .await + .map_err(|_| StatusCode::UNAUTHORIZED)?; + + if !token_is_valid(auth.token()) { + return Err(StatusCode::UNAUTHORIZED); + } + + // get the request back so we can run `next` + // + // `try_into_request` will fail if you have extracted the request body. We + // know that `TypedHeader` never does that. + // + // see the `consume-body-in-extractor-or-middleware` example if you need to + // extract the body + let request = request_parts.try_into_request().expect("body extracted"); + + Ok(next.run(request).await) +} + +fn token_is_valid(token: &str) -> bool { + // ... + # false +} + +let app = Router::new().layer(middleware::from_fn(auth_middleware)); +# let _: Router = app; +``` + [`body::Body`]: crate::body::Body [customize-extractor-error]: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs [`HeaderMap`]: https://docs.rs/http/latest/http/header/struct.HeaderMap.html