#middleware #http-header #content-negotiation #request-response #axum-middleware

axum-content-negotiation

Axum 中间件,用于使用 Accept 和 Content-Type 头以不同格式序列化

2 个版本

0.1.1 2024 年 4 月 27 日
0.1.0 2024 年 2 月 4 日

#553 in 解析器实现

Download history 152/week @ 2024-04-23 17/week @ 2024-04-30

每月 90 次下载

MIT/Apache

42KB
773

axum-content-negotiation

Axum 的 HTTP 内容协商中间件和提取器。


一组 Axum 层和提取器,使用 AcceptContent-Type 头进行内容协商。它实现了无模式的序列化和反序列化内容协商。目前支持的编码有

  • application/json
  • application/cbor

安装

[dependencies]
axum-content-negotiation = "0.1"

特性

以下特性可以被启用以包括对不同编码的支持

  • simd-json (默认): 启用对 application/json 编码的支持,使用 simd-json
  • cbor (默认): 启用对 application/cbor 编码的支持,使用 cbor4ii
  • json: 启用对 application/json 编码的支持,使用 serde_json

以下特性在 Accept 头缺失或存在 Accept: * 时启用默认内容类型

  • default-json (默认): 假设 application/json 为默认内容类型。
  • default-cbor: 假设 application/cbor 为默认内容类型。

为了自定义依赖项,您可以按如下方式启用或禁用特性

[dependencies]
axum-content-negotiation = { version = "0.1", default-features = false, features = ["json", "default-json"] }

用法

请求负载

axum_content_negotiation::NegotiateExtractor,可以在 Axum 处理程序中使用它来接受多个 Content-Type 格式的请求体。此提取器将尝试根据 Content-Type 头和一组支持的无模式编码将请求体反序列化到所需的类型。

use axum::{http::StatusCode, response::IntoResponse, routing::post, Router};
use axum_content_negotiation::Negotiate;

#[derive(serde::Deserialize, Debug)]
struct YourType {
    name: String,
}

async fn handler(Negotiate(request_body): Negotiate<YourType>) -> impl IntoResponse {
    (StatusCode::OK, format!("Received ${:?}", request_body))
}

let router: Router<()> = Router::new().route("/", post(handler));

响应负载

为了响应正确的 Content-Type 头,axum_content_negotiation::Negotiate 还实现了 IntoResponse 特性,但它需要 axum_content_negotiation::NegotiateLayer 才能在实际格式上执行序列化。

use axum::{http::StatusCode, response::IntoResponse, routing::get, Router};
use axum_content_negotiation::{Negotiate, NegotiateLayer};

#[derive(serde::Serialize)]
struct YourType {
    name: String,
}

async fn handler() -> impl IntoResponse {
    let response = YourType {
        name: "John".to_string(),
    };
    (StatusCode::OK, Negotiate(response))
}

let router: Router<()> = Router::new().route("/", get(handler)).layer(NegotiateLayer);

综合起来

use axum::{http::StatusCode, response::IntoResponse, routing::*, Router};
use axum_content_negotiation::{Negotiate, NegotiateLayer};

#[derive(serde::Deserialize, Debug)]
struct Input {
    name: String,
}

#[derive(serde::Serialize)]
struct Output {
    name: String,
}

async fn handler(Negotiate(request_body): Negotiate<Input>) -> impl IntoResponse {
    let response = Output {
        name: format!("Hello there, {}!", request_body.name),
    };
    (StatusCode::OK, Negotiate(response))
}

let router: Router<()> = Router::new().route("/", put(handler)).layer(NegotiateLayer);

依赖项

~12MB
~213K SLoC