sozu_lib/protocol/kawa_h1/
diagnostics.rs1use std::fmt::Write;
2
3use kawa::{ParsingErrorKind, ParsingPhase, ParsingPhaseMarker};
4
5use super::GenericHttpStream;
6
7#[cfg(feature = "tolerant-http1-parser")]
8const CHARSET: &str = "all characters are LATIN-1 (no UTF-8 allowed)";
9#[cfg(not(feature = "tolerant-http1-parser"))]
10const CHARSET: &str = "all characters are UASCII (no UTF-8 allowed)";
11
12fn hex_dump(buffer: &[u8], window: usize, start: usize, end: usize) -> String {
13 let mut result = String::with_capacity(window * 3 + 10);
14 result.push('\"');
15 if end - start <= window {
16 let slice = &buffer[start..end];
17 for (i, c) in slice.iter().enumerate() {
18 let _ = write!(result, "{c:02x}");
19 if i < slice.len() - 1 {
20 result.push(' ');
21 }
22 }
23 } else {
24 let half = window / 2;
25 let slice1 = &buffer[start..start + half - 1];
26 let slice2 = &buffer[end - half + 1..end];
27 for c in slice1 {
28 let _ = write!(result, "{c:02x} ");
29 }
30 result.push_str("… ");
31 for (i, c) in slice2.iter().enumerate() {
32 let _ = write!(result, "{c:02x}");
33 if i < slice2.len() - 1 {
34 result.push(' ');
35 }
36 }
37 }
38 result.push('\"');
39 result
40}
41
42pub fn diagnostic_400_502(
43 marker: ParsingPhaseMarker,
44 kind: ParsingErrorKind,
45 kawa: &GenericHttpStream,
46) -> (String, String, String, String) {
47 match kind {
48 ParsingErrorKind::Consuming { index } => {
49 let message = match marker {
50 ParsingPhaseMarker::StatusLine => {
51 format!(
52 "The status line is invalid. Make sure it is well formated and {CHARSET}."
53 )
54 }
55 ParsingPhaseMarker::Headers | ParsingPhaseMarker::Trailers => {
56 let marker = if marker == ParsingPhaseMarker::Headers {
57 "header"
58 } else {
59 "trailer"
60 };
61 format!("A {marker} is invalid, make sure {CHARSET}.")
62 }
63 ParsingPhaseMarker::Cookies => {
64 format!("A cookie is invalid, make sure {CHARSET}.")
65 }
66 ParsingPhaseMarker::Body
67 | ParsingPhaseMarker::Chunks
68 | ParsingPhaseMarker::Terminated
69 | ParsingPhaseMarker::Error => {
70 "The parser stopped in an unexpected phase.".into()
71 }
72 };
73 let buffer = kawa.storage.buffer();
74 let successfully_parsed = hex_dump(buffer, 32, kawa.storage.start, kawa.storage.head);
75 let partially_parsed = hex_dump(buffer, 32, kawa.storage.head, index as usize);
76 let invalid = hex_dump(buffer, 32, index as usize, kawa.storage.end);
77 (message, successfully_parsed, partially_parsed, invalid)
78 }
79 ParsingErrorKind::Processing { message } => (
80 format!("The request is correctly structured but presents inconsistent or invalid values: {message}."),
81 "null".into(),
82 "null".into(),
83 "null".into(),
84 ),
85 }
86}
87
88pub fn diagnostic_413_507(parsing_phase: ParsingPhase) -> String {
89 match parsing_phase {
90 kawa::ParsingPhase::StatusLine => {
91 "Status line is too long. Note that an URL should not exceed 2083 characters.".into()
92 }
93 kawa::ParsingPhase::Headers | kawa::ParsingPhase::Cookies { .. } => {
94 "Headers are too long. All headers should fit in a single buffer.".into()
95 }
96 _ => "The parser stopped in an unexpected phase.".into(),
97 }
98}