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/// Terminal output of a successful HTTP request-response exchange.
16#[derive(Clone, Debug)]
17pub struct HttpSendOutput {
18 /// The parsed response, body included.
19 pub response: HttpResponse,
20 /// Bytes already buffered past the end of the response.
21 pub remaining: Vec<u8>,
22 /// Whether the server signalled the connection can be reused.
23 pub keep_alive: bool,
24}
25
26/// Per-step yield emitted by `Http10Send` / `Http11Send`; adds
27/// [`Self::WantsRedirect`] to the standard [`HttpYield`] for 3xx responses.
28#[derive(Debug)]
29pub enum HttpSendYield {
30 /// The coroutine wants bytes read from the stream and handed back
31 /// on the next resume.
32 WantsRead,
33 /// The coroutine wants these bytes written to the stream.
34 WantsWrite(Vec<u8>),
35 /// The server answered with a 3xx and a parseable location; the
36 /// caller decides whether to follow.
37 WantsRedirect {
38 /// The redirect target, resolved against the request URL.
39 url: Url,
40 /// The 3xx response itself.
41 response: HttpResponse,
42 /// Whether the server signalled the connection can be reused.
43 keep_alive: bool,
44 /// `false` when the redirect crosses scheme/host/port; do not
45 /// forward credentials without user consent (RFC 9110 ยง15.4).
46 same_origin: bool,
47 },
48}
49
50impl From<HttpYield> for HttpSendYield {
51 fn from(y: HttpYield) -> Self {
52 match y {
53 HttpYield::WantsRead => Self::WantsRead,
54 HttpYield::WantsWrite(bytes) => Self::WantsWrite(bytes),
55 }
56 }
57}