Skip to main content

ringline_http/
streaming.rs

1//! Streaming response types for incremental body delivery.
2
3use bytes::Bytes;
4
5use crate::error::HttpError;
6use crate::h1_conn::H1StreamingResponse;
7use crate::h2_conn::H2StreamingResponse;
8
9/// A streaming HTTP response that yields body chunks incrementally.
10///
11/// Wraps either an HTTP/2 or HTTP/1.1 streaming response. The connection
12/// is borrowed exclusively while this type exists — no other requests can
13/// be sent until the body is fully consumed or the response is dropped.
14///
15/// # Example
16///
17/// ```rust,ignore
18/// let mut stream = client.post("/v1/chat/completions")
19///     .header("content-type", "application/json")
20///     .body(payload)
21///     .send_streaming()
22///     .await?;
23///
24/// assert_eq!(stream.status(), 200);
25/// while let Some(chunk) = stream.next_chunk().await? {
26///     // process each body chunk as it arrives
27/// }
28/// ```
29pub enum StreamingResponse<'a> {
30    H2(H2StreamingResponse<'a>),
31    H1(H1StreamingResponse<'a>),
32}
33
34impl StreamingResponse<'_> {
35    /// HTTP status code.
36    pub fn status(&self) -> u16 {
37        match self {
38            Self::H2(s) => s.status(),
39            Self::H1(s) => s.status(),
40        }
41    }
42
43    /// Response headers as (name, value) pairs.
44    pub fn headers(&self) -> &[(String, String)] {
45        match self {
46            Self::H2(s) => s.headers(),
47            Self::H1(s) => s.headers(),
48        }
49    }
50
51    /// Get the first header value matching `name` (case-insensitive).
52    pub fn header(&self, name: &str) -> Option<&str> {
53        match self {
54            Self::H2(s) => s.header(name),
55            Self::H1(s) => s.header(name),
56        }
57    }
58
59    /// Yield the next body chunk, or `None` when the body is complete.
60    pub async fn next_chunk(&mut self) -> Result<Option<Bytes>, HttpError> {
61        match self {
62            Self::H2(s) => s.next_chunk().await,
63            Self::H1(s) => s.next_chunk().await,
64        }
65    }
66}