You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust Axum中用结构体接收自定义请求头及TypedHeader示例

使用Axum的TypedHeader接收自定义请求头

TypedHeader完全支持自定义请求头,只需为每个自定义头实现Header trait即可。以下是两种实现方案,既可以单独接收每个自定义头,也可以封装成结构体统一接收。


方案1:单独接收每个自定义头(推荐用headers宏简化)

首先在Cargo.toml中添加依赖(如果还没加):

[dependencies]
axum = "0.7"
http = "1.0"
headers = "0.4"
serde = { version = "1.0", features = ["derive"] }

然后用headers宏快速定义自定义请求头,无需手动实现Header trait:

use headers::Header;
use axum::extract::TypedHeader;

// 定义Y-VERSION自定义头
headers::header! {
    (YVersion, "Y-VERSION") => [String]
}

// 定义Z-TYPE自定义头
headers::header! {
    (ZType, "Z-TYPE") => [String]
}

// 定义Z-SESSION自定义头
headers::header! {
    (ZSession, "Z-SESSION") => [String]
}

接下来修改处理器签名,直接通过TypedHeader提取每个自定义头:

#[debug_handler]
pub async fn find_balance(
    Path(balance_string): Path<String>,
    query_params: Query<QueryParams>,
    TypedHeader(y_version): TypedHeader<YVersion>,
    TypedHeader(z_type): TypedHeader<ZType>,
    TypedHeader(z_session): TypedHeader<ZSession>,
    JwtClaims(user): JwtClaims<RegisteredClaims>,
    State(client): State<Client>
) -> Result<Json<BalanceDTO>, Error> {
    // 使用自定义头的值
    let version = y_version.0;
    let type_ = z_type.0;
    let session = z_session.0;
    
    // 后续业务逻辑...
}

方案2:封装成结构体统一接收

如果你希望像Query那样用一个结构体接收所有自定义头,可以实现FromRequest trait:

use axum::{
    extract::FromRequest,
    http::{Request, StatusCode, Error},
    async_trait,
};

// 注意:`type`是Rust关键字,改用`type_`或`r#type`
#[derive(Debug, Clone)]
pub struct CustomHeaders {
    pub version: String,
    pub type_: String,
    pub session: String,
}

#[async_trait]
impl<S> FromRequest<S> for CustomHeaders
where
    S: Send + Sync,
{
    type Rejection = Error;

    async fn from_request(req: Request<axum::body::Body>, _state: &S) -> Result<Self, Self::Rejection> {
        let headers = req.headers();

        // 提取并校验每个自定义头
        let version = headers.get("Y-VERSION")
            .ok_or_else(|| Error::from_http_status_code(StatusCode::BAD_REQUEST))?
            .to_str()
            .map_err(|_| Error::from_http_status_code(StatusCode::BAD_REQUEST))?
            .to_string();

        let type_ = headers.get("Z-TYPE")
            .ok_or_else(|| Error::from_http_status_code(StatusCode::BAD_REQUEST))?
            .to_str()
            .map_err(|_| Error::from_http_status_code(StatusCode::BAD_REQUEST))?
            .to_string();

        let session = headers.get("Z-SESSION")
            .ok_or_else(|| Error::from_http_status_code(StatusCode::BAD_REQUEST))?
            .to_str()
            .map_err(|_| Error::from_http_status_code(StatusCode::BAD_REQUEST))?
            .to_string();

        Ok(Self { version, type_, session })
    }
}

然后在处理器中直接使用这个结构体:

#[debug_handler]
pub async fn find_balance(
    Path(balance_string): Path<String>,
    query_params: Query<QueryParams>,
    custom_headers: CustomHeaders,
    JwtClaims(user): JwtClaims<RegisteredClaims>,
    State(client): State<Client>
) -> Result<Json<BalanceDTO>, Error> {
    // 直接访问结构体字段
    println!("Version: {}", custom_headers.version);
    println!("Type: {}", custom_headers.type_);
    println!("Session: {}", custom_headers.session);
    
    // 后续业务逻辑...
}

内容的提问来源于stack exchange,提问作者swerts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:06:33