Function axum::middleware::from_fn
source · [−]pub fn from_fn<F>(f: F) -> FromFnLayer<F>
Expand description
Create a middleware from an async function.
from_fn
requires the function given to
- Be an
async fn
. - Take
Request<B>
as the first argument. - Take
Next<B>
as the second argument. - Return something that implements
IntoResponse
.
Example
use axum::{
Router,
http::{Request, StatusCode},
routing::get,
response::IntoResponse,
middleware::{self, Next},
};
async fn auth<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse {
let auth_header = req.headers()
.get(http::header::AUTHORIZATION)
.and_then(|header| header.to_str().ok());
match auth_header {
Some(auth_header) if token_is_valid(auth_header) => {
Ok(next.run(req).await)
}
_ => Err(StatusCode::UNAUTHORIZED),
}
}
fn token_is_valid(token: &str) -> bool {
// ...
}
let app = Router::new()
.route("/", get(|| async { /* ... */ }))
.route_layer(middleware::from_fn(auth));
Passing state
State can be passed to the function like so:
use axum::{
Router,
http::{Request, StatusCode},
routing::get,
response::IntoResponse,
middleware::{self, Next}
};
#[derive(Clone)]
struct State { /* ... */ }
async fn my_middleware<B>(
req: Request<B>,
next: Next<B>,
state: State,
) -> impl IntoResponse {
// ...
}
let state = State { /* ... */ };
let app = Router::new()
.route("/", get(|| async { /* ... */ }))
.route_layer(middleware::from_fn(move |req, next| {
my_middleware(req, next, state.clone())
}));
Or via extensions:
use axum::{
Router,
extract::Extension,
http::{Request, StatusCode},
routing::get,
response::IntoResponse,
middleware::{self, Next},
};
use tower::ServiceBuilder;
#[derive(Clone)]
struct State { /* ... */ }
async fn my_middleware<B>(
req: Request<B>,
next: Next<B>,
) -> impl IntoResponse {
let state: &State = req.extensions().get().unwrap();
// ...
}
let state = State { /* ... */ };
let app = Router::new()
.route("/", get(|| async { /* ... */ }))
.layer(
ServiceBuilder::new()
.layer(Extension(state))
.layer(middleware::from_fn(my_middleware)),
);