axum_streams/
lib.rs

1#![allow(unused_parens, clippy::new_without_default)]
2#![forbid(unsafe_code)]
3
4//! # axum HTTP streaming body support for different formats:
5//! - JSON array stream format
6//! - JSON Lines (NL/NewLines) format
7//! - CSV stream format
8//! - Protobuf len-prefixed stream format
9//! - Arrow IPC stream format
10//! - Text stream format
11//!
12//! [JSON Streaming](https://en.wikipedia.org/wiki/JSON_streaming) is a term referring to streaming a
13//! stream of element as independent JSON objects as a continuous HTTP request or response.
14//!
15//! This type of responses are useful when you are reading huge stream of objects from some source (such as database, file, etc)
16//! and want to avoid huge memory allocations to store on the server side.
17//!
18//! # Example
19//!
20//! ```rust
21//! use axum::{
22//!     Router,
23//!     routing::get,
24//!     http::{StatusCode, header::CONTENT_TYPE},
25//!     response::{Response, IntoResponse},
26//! };
27//! use futures::Stream;
28//! use axum_streams::*;
29//! use serde::Serialize;
30//!
31//! #[derive(Debug, Clone, Serialize)]
32//! struct MyTestStructure {
33//!     some_test_field: String
34//! }
35//!
36//! // Your possibly stream of objects
37//! fn my_source_stream() -> impl Stream<Item=MyTestStructure> {
38//!     // Simulating a stream with a plain vector and throttling to show how it works
39//!     use tokio_stream::StreamExt;
40//!     futures::stream::iter(vec![
41//!         MyTestStructure {
42//!             some_test_field: "test1".to_string()
43//!         }; 1000
44//!     ]).throttle(std::time::Duration::from_millis(50))
45//! }
46//!
47//! // Route implementation:
48//! async fn test_json_array_stream() -> impl IntoResponse {
49//!     StreamBodyAs::json_array(my_source_stream())
50//! }
51//! async fn test_json_nl_stream() -> impl IntoResponse {
52//!     StreamBodyAs::json_nl(my_source_stream())
53//! }
54//!
55//! async fn test_csv_stream() -> impl IntoResponse {
56//!     StreamBodyAs::csv(my_source_stream())
57//!     // Which is the same as:
58//!     // StreamBodyWith::new(CsvStreamFormat::new(
59//!     //    true, // with_header
60//!     //    b',' // CSV delimiter
61//!     //), my_source_stream())
62//! }
63//!
64//! ```
65//! ## Need client support?
66//! There is the same functionality for:
67//! - [reqwest-streams](https://github.com/abdolence/reqwest-streams-rs).
68//!
69
70#![allow(clippy::new_without_default, clippy::needless_lifetimes)]
71
72mod stream_format;
73pub use stream_format::*;
74
75mod stream_body_as;
76pub use self::stream_body_as::HttpHeaderValue;
77pub use self::stream_body_as::StreamBodyAs;
78pub use self::stream_body_as::StreamBodyAsOptions;
79
80mod envelope;
81pub use envelope::*;
82
83#[cfg(feature = "json")]
84mod json_formats;
85#[cfg(feature = "json")]
86pub use json_formats::JsonArrayStreamFormat;
87#[cfg(feature = "json")]
88pub use json_formats::JsonNewLineStreamFormat;
89
90#[cfg(feature = "csv")]
91mod csv_format;
92#[cfg(feature = "csv")]
93pub use csv::{QuoteStyle, Terminator};
94#[cfg(feature = "csv")]
95pub use csv_format::CsvStreamFormat;
96
97#[cfg(feature = "text")]
98mod text_format;
99#[cfg(feature = "text")]
100pub use text_format::TextStreamFormat;
101
102#[cfg(feature = "protobuf")]
103mod protobuf_format;
104#[cfg(feature = "protobuf")]
105pub use protobuf_format::ProtobufStreamFormat;
106
107#[cfg(feature = "arrow")]
108mod arrow_format;
109#[cfg(feature = "arrow")]
110pub use arrow_format::ArrowRecordBatchIpcStreamFormat;
111
112#[cfg(test)]
113mod test_client;