在Axum中,中间件是处理请求和响应的强大工具。
它们可以在请求到达实际处理程序之前或响应发回客户端之前对其进行处理。
Axum提供了多种方式来实现中间件。
本文将介绍两种常用的 方法:使用from_fn和tower::Layer。
方式一:from_fn
from_fn是一种简便的方法,可以快速创建中间件。它适用于那些不需要复杂逻辑的中间件。
示例代码: request_id
以下是一个通过from_fn实现请求ID中间件的示例:
// request_id.rs
use super::REQUEST_ID_HEADER;
use axum::{extract::Request, http::HeaderValue, middleware::Next, response::Response};
use tracing::warn;
pub async fn set_request_id(mut req: Request, next: Next) -> Response {
let id = match req.headers().get(REQUEST_ID_HEADER) {
Some(v) => Some(v.clone()),
None => {
let request_id = uuid::Uuid::new_v4().to_string();
match HeaderValue::from_str(&request_id) {
Ok(v) => {
req.headers_mut().insert(REQUEST_ID_HEADER, v.clone());
Some(v)
}
Err(e) => {
warn!("parse generated request id failed: {}", e);
None
}
}
}
};
let mut res = next.run(req).await;
if let Some(id) = id {
res.headers_mut().insert(REQUEST_ID_HEADER, id);
}
res
}
在这个示例中,中间件会检查请求头中是否包含请求ID。 如果没有,则生成一个新的UUID并将其添加到请求头中。 然后,继续处理请求并在响应头中添加相同的请求ID。
Token验证中间件
这里再提供一个示例,展示如何实现一个验证Token的中间件:
// auth.rs
use crate::AppState;
use axum::{
extract::{FromRequestParts, Request, State},
http::StatusCode,
middleware::Next,
response::{IntoResponse, Response},
};
use axum_extra::{
headers::{authorization::Bearer, Authorization},
TypedHeader;
use tracing::warn;
pub async fn verify_token(State(state): State<AppState>, req: Request, next: Next) -> Response {
let (mut parts, body) = req.into_parts();
let req = match TypedHeader::<Authorization<Bearer>>::from_request_parts(&mut parts, &state).await {
Ok(TypedHeader(Authorization(bearer))) => {
let token = bearer.token();
match state.dk.verify(token) {
Ok(user) => {
let mut req = Request::from_parts(parts, body);
req.extensions_mut().insert(user);
req
}
Err(e) => {
let msg = format!("verify token failed: {}", e);
warn!(msg);
return (StatusCode::FORBIDDEN, msg).into_response();
}
}
}
Err(e) => {
let msg = format!("parse Authorization header failed: {}", e);
warn!(msg);
return (StatusCode::UNAUTHORIZED, msg).into_response();
}
};
next.run(req).await
}
在这个示例中,中间件会检查请求头中的Authorization Bearer token,并验证其有效性。 如果验证失败,将返回相应的错误响应。