Skip to main content

io_http/rfc9110/
send.rs

1//! Shared output and yield types for HTTP request-response coroutines.
2//!
3//! Both [`Http10Send`] and [`Http11Send`] return [`HttpSendOutput`] on
4//! success and emit [`HttpSendYield`] on every intermediate step.
5//!
6//! [`Http10Send`]: crate::rfc1945::send::Http10Send
7//! [`Http11Send`]: crate::rfc9112::send::Http11Send
8
9use alloc::vec::Vec;
10
11use url::Url;
12
13use crate::{coroutine::HttpYield, rfc9110::response::HttpResponse};
14
15/// Default maximum size in bytes of a buffered response body: 256 MiB.
16///
17/// Generous enough for large attachments and exports, small enough
18/// that a hostile or broken server cannot exhaust memory. Callers
19/// expecting bigger bodies raise the `max_body_len` field of the
20/// coroutine they drive.
21pub const HTTP_DEFAULT_MAX_BODY_LEN: usize = 256 * 1024 * 1024;
22
23/// Terminal output of a successful HTTP request-response exchange.
24#[derive(Clone, Debug)]
25pub struct HttpSendOutput {
26    /// The parsed response, body included.
27    pub response: HttpResponse,
28    /// Bytes already buffered past the end of the response.
29    pub remaining: Vec<u8>,
30    /// Whether the server signalled the connection can be reused.
31    pub keep_alive: bool,
32}
33
34/// Per-step yield emitted by `Http10Send` / `Http11Send`; adds
35/// [`Self::WantsRedirect`] to the standard [`HttpYield`] for 3xx responses.
36#[derive(Debug)]
37pub enum HttpSendYield {
38    /// The coroutine wants bytes read from the stream and handed back
39    /// on the next resume.
40    WantsRead,
41    /// The coroutine wants these bytes written to the stream.
42    WantsWrite(Vec<u8>),
43    /// The server answered with a 3xx and a parseable location; the
44    /// caller decides whether to follow.
45    WantsRedirect {
46        /// The redirect target, resolved against the request URL.
47        url: Url,
48        /// The 3xx response itself.
49        response: HttpResponse,
50        /// Whether the server signalled the connection can be reused.
51        keep_alive: bool,
52        /// `false` when the redirect crosses scheme/host/port; do not
53        /// forward credentials without user consent (RFC 9110 ยง15.4).
54        same_origin: bool,
55    },
56}
57
58impl From<HttpYield> for HttpSendYield {
59    fn from(y: HttpYield) -> Self {
60        match y {
61            HttpYield::WantsRead => Self::WantsRead,
62            HttpYield::WantsWrite(bytes) => Self::WantsWrite(bytes),
63        }
64    }
65}