Skip to main content

sozu_lib/protocol/kawa_h1/
mod.rs

1//! HTTP/1.1 building blocks shared with the `mux` datapath.
2//!
3//! Since the `mux` migration this module no longer owns a session state
4//! machine. `HttpStateMachine` (`lib/src/http.rs`) and `HttpsStateMachine`
5//! (`lib/src/https.rs`) drive HTTP/1.1 through `protocol::mux` in H1 mode,
6//! and the `Http<Front, L>` session that used to live here was removed on
7//! 2026-09-20 (sozu#1346) once a `panic!` probe proved no binary
8//! constructed it.
9//!
10//! What remains is the H1 vocabulary `mux` builds on:
11//!
12//! - [`DefaultAnswer`] — the catalogue of synthesised replies, rendered by
13//!   `answers::HttpAnswers` and selected by `mux::answers`;
14//! - `editor::HttpContext` — per-request state plus the Kawa parser
15//!   callbacks that rewrite `Forwarded` / `X-Forwarded-*` / `Sozu-Id`;
16//! - `parser::Method` and `parser::hostname_and_port` — the owned-string-free
17//!   method enum and the authority splitter used by the mux router.
18//!
19//! Long-form map: `lib/src/protocol/kawa_h1/LIFECYCLE.md`.
20
21pub mod answers;
22pub mod editor;
23pub mod parser;
24
25use crate::pool::Checkout;
26
27/// Generic Http representation using the Kawa crate using the Checkout of Sozu as buffer
28type GenericHttpStream = kawa::Kawa<Checkout>;
29
30impl kawa::AsBuffer for Checkout {
31    fn as_buffer(&self) -> &[u8] {
32        self.inner.extra()
33    }
34    fn as_mut_buffer(&mut self) -> &mut [u8] {
35        self.inner.extra_mut()
36    }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum DefaultAnswer {
41    Answer301 {
42        location: String,
43    },
44    /// RFC 9110 §15.4.3 — temporary redirect; user agents may rewrite POST
45    /// to GET on follow. Surfaced by `RedirectPolicy::Found` (#1009).
46    Answer302 {
47        location: String,
48    },
49    /// RFC 9110 §15.4.9 — permanent redirect that PRESERVES the request
50    /// method on follow (no GET-rewrite on POST). Surfaced by
51    /// `RedirectPolicy::PermanentRedirect` (#1009).
52    Answer308 {
53        location: String,
54    },
55    Answer400 {
56        message: String,
57        phase: kawa::ParsingPhaseMarker,
58        successfully_parsed: String,
59        partially_parsed: String,
60        invalid: String,
61    },
62    Answer401 {
63        /// Optional `WWW-Authenticate` value (e.g. `Basic realm="…"`).
64        /// When `None` or empty the realm header line is elided by the
65        /// template engine so the response stays a bare 401.
66        www_authenticate: Option<String>,
67    },
68    Answer404 {},
69    Answer408 {
70        duration: String,
71    },
72    Answer413 {
73        message: String,
74        phase: kawa::ParsingPhaseMarker,
75        capacity: usize,
76    },
77    /// RFC 9110 §15.5.20 — returned when the request's `:authority` / `Host`
78    /// host does not match the TLS SNI negotiated for this connection.
79    /// The peer may retry on a fresh TLS connection that negotiates an SNI
80    /// matching the authority.
81    Answer421 {},
82    /// RFC 6585 §4 — emitted when the per-(cluster, source-IP) connection
83    /// limit is reached. `retry_after` is the suggested wait, in seconds;
84    /// `None` (or `Some(0)`) tells the template engine to omit the header
85    /// — `Retry-After: 0` invites an immediate retry that defeats the
86    /// limit.
87    Answer429 {
88        retry_after: Option<u32>,
89    },
90    Answer502 {
91        message: String,
92        phase: kawa::ParsingPhaseMarker,
93        successfully_parsed: String,
94        partially_parsed: String,
95        invalid: String,
96    },
97    Answer503 {
98        message: String,
99    },
100    Answer504 {
101        duration: String,
102    },
103    Answer507 {
104        phase: kawa::ParsingPhaseMarker,
105        message: String,
106        capacity: usize,
107    },
108}
109
110impl From<&DefaultAnswer> for u16 {
111    fn from(answer: &DefaultAnswer) -> u16 {
112        match answer {
113            DefaultAnswer::Answer301 { .. } => 301,
114            DefaultAnswer::Answer302 { .. } => 302,
115            DefaultAnswer::Answer308 { .. } => 308,
116            DefaultAnswer::Answer400 { .. } => 400,
117            DefaultAnswer::Answer401 { .. } => 401,
118            DefaultAnswer::Answer404 { .. } => 404,
119            DefaultAnswer::Answer408 { .. } => 408,
120            DefaultAnswer::Answer413 { .. } => 413,
121            DefaultAnswer::Answer421 { .. } => 421,
122            DefaultAnswer::Answer429 { .. } => 429,
123            DefaultAnswer::Answer502 { .. } => 502,
124            DefaultAnswer::Answer503 { .. } => 503,
125            DefaultAnswer::Answer504 { .. } => 504,
126            DefaultAnswer::Answer507 { .. } => 507,
127        }
128    }
129}