#http-response #stream #http #web #web-framework #http-body #axus

axum-streams

Axum 的 HTTP 响应流支持:json/csv/protobuf/arrow/txt

21 个版本 (13 个重大变更)

0.18.0 2024 年 7 月 12 日
0.16.0 2024 年 6 月 20 日
0.14.0 2024 年 3 月 31 日
0.12.0 2023 年 12 月 11 日
0.5.0 2022 年 7 月 31 日

#246Web 编程

Download history 1339/week @ 2024-05-03 1501/week @ 2024-05-10 1463/week @ 2024-05-17 824/week @ 2024-05-24 907/week @ 2024-05-31 878/week @ 2024-06-07 1044/week @ 2024-06-14 1058/week @ 2024-06-21 649/week @ 2024-06-28 608/week @ 2024-07-05 873/week @ 2024-07-12 944/week @ 2024-07-19 997/week @ 2024-07-26 829/week @ 2024-08-02 1085/week @ 2024-08-09 1133/week @ 2024-08-16

每月下载量 4,256
reqwest-streams 中使用

Apache-2.0

70KB
1.5K SLoC

Cargo tests and formatting security audit

Rust 的 axum streams

库为 axum 网络框架 提供 HTTP 响应流支持

  • JSON 数组流格式
    • 当您需要在某些对象(例如第一个级别)内部包含数组时,支持简单包装结构
  • JSON 行流格式
  • CSV 流
  • Protobuf 长度前缀流格式
  • Apache Arrow IPC 流格式
  • 文本流

此类响应在您需要从某些来源(如数据库、文件等)读取大量对象流时非常有用,并且希望避免大量内存分配。

快速入门

Cargo.toml

[dependencies]
axum-streams = { version = "0.18", features=["json", "csv", "protobuf", "text"] }

兼容性矩阵

axum axum-streams
0.7 v0.11+
0.6 v0.9-v0.10
0.5 0.7

示例代码


#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyTestStructure {
  some_test_field: String
}

fn my_source_stream() -> impl Stream<Item=MyTestStructure> {
  // Simulating a stream with a plain vector and throttling to show how it works
  stream::iter(vec![
    MyTestStructure {
      some_test_field: "test1".to_string()
    }; 1000
  ]).throttle(std::time::Duration::from_millis(50))
}

async fn test_json_array_stream() -> impl IntoResponse {
  StreamBodyAs::json_array(source_test_stream())
}

async fn test_json_nl_stream() -> impl IntoResponse {
  StreamBodyAs::json_nl(source_test_stream())
}

async fn test_csv_stream() -> impl IntoResponse {
  StreamBodyAs::csv(source_test_stream())
}

async fn test_text_stream() -> impl IntoResponse {
  StreamBodyAs::text(source_test_stream())
}

所有示例均可在 examples 目录 中找到。

要运行示例,请使用

# cargo run --example json-example --features json

需要客户端支持?

对于以下功能,也存在相同的功能

帧大小的配置

默认情况下,库为流中的每个项目生成一个 HTTP 帧。您可以使用 StreamAsOptions 来更改此设置

    StreamBodyAsOptions::new().buffering_ready_items(1000)
        .json_array(source_test_stream())

错误处理

库提供了一种在流中传播错误的方式

struct MyError {
    message: String,
}

impl Into<axum::Error> for MyError {
    fn into(self) -> axum::Error {
        axum::Error::new(self.message)
    }
}

fn my_source_stream() -> impl Stream<Item=Result<MyTestStructure, MyError>> {
  // Simulating a stream with a plain vector and throttling to show how it works
  stream::iter(vec![
    Ok(MyTestStructure {
      some_test_field: "test1".to_string()
    }); 1000
  ])
}

async fn test_json_array_stream() -> impl IntoResponse {
  // Use _with_errors functions or directly `StreamBodyAs::with_options` 
  // to produce a stream with errors
  StreamBodyAs::json_array_with_errors(source_test_stream())
}

另一个对象内的 JSON 数组

有时您需要在某些对象内包含您的数组,例如

{
  "some_status_field": "ok",
  "data": [
    {
      "some_test_field": "test1"
    },
    {
      "some_test_field": "test2"
    }
  ]
}

包含 data 字段的包装对象称为信封。

您需要定义这两个结构:信封和记录

#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyEnvelopeStructure {
    something_else: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    data: Vec<MyItem>
}

#[derive(Debug, Clone, Deserialize, Serialize)]
struct MyItem {
  some_test_field: String
}

并使用 json_array_with_envelope 代替 json_array。有关详细信息,请参阅 json-array-complex-structure.rs

支持有限

  • 仅支持第一层嵌套以避免具有性能影响的复杂实现。
  • 您需要从 envelope 结构中移除目标数组字段,或者使用这个 Serde 技巧来避免 JSON 序列化问题。
    #[serde(skip_serializing_if = "Vec::is_empty")]

许可证

Apache 软件许可证 (ASL)

作者

Abdulla Abdurakhmanov

依赖项

约 6–15MB
约 178K SLoC