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}