1#[derive(Debug, Clone, PartialEq, Eq)]
3pub enum HttpError {
4 Malformed(&'static str),
6 TooManyHeaders,
8 HeadTooLarge {
10 max: usize,
12 },
13 BufferFull {
15 needed: usize,
17 available: usize,
19 },
20 BufferTooSmall {
22 needed: usize,
24 available: usize,
26 },
27 InvalidHeaderValue,
29}
30
31impl std::fmt::Display for HttpError {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 Self::Malformed(ctx) => write!(f, "malformed HTTP: {ctx}"),
35 Self::TooManyHeaders => write!(f, "too many HTTP headers"),
36 Self::HeadTooLarge { max } => write!(f, "HTTP head exceeds {max} bytes"),
37 Self::BufferFull { needed, available } => {
38 write!(f, "buffer full: need {needed}, {available} available")
39 }
40 Self::BufferTooSmall { needed, available } => {
41 write!(
42 f,
43 "write buffer too small: need {needed} bytes, have {available}"
44 )
45 }
46 Self::InvalidHeaderValue => {
47 write!(f, "header name or value contains CR/LF")
48 }
49 }
50 }
51}
52
53impl std::error::Error for HttpError {}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn http_error_malformed() {
61 let err = HttpError::Malformed("missing status line");
62 assert!(matches!(err, HttpError::Malformed("missing status line")));
63 assert_eq!(err.to_string(), "malformed HTTP: missing status line");
64 }
65
66 #[test]
67 fn http_error_too_many_headers() {
68 let err = HttpError::TooManyHeaders;
69 assert!(matches!(err, HttpError::TooManyHeaders));
70 assert_eq!(err.to_string(), "too many HTTP headers");
71 }
72
73 #[test]
74 fn http_error_head_too_large() {
75 let err = HttpError::HeadTooLarge { max: 8192 };
76 assert!(matches!(err, HttpError::HeadTooLarge { max: 8192 }));
77 assert_eq!(err.to_string(), "HTTP head exceeds 8192 bytes");
78 }
79
80 #[test]
81 fn http_error_buffer_full() {
82 let err = HttpError::BufferFull {
83 needed: 1024,
84 available: 256,
85 };
86 assert!(matches!(
87 err,
88 HttpError::BufferFull {
89 needed: 1024,
90 available: 256,
91 }
92 ));
93 assert_eq!(err.to_string(), "buffer full: need 1024, 256 available");
94 }
95
96 #[test]
97 fn http_error_buffer_too_small() {
98 let err = HttpError::BufferTooSmall {
99 needed: 512,
100 available: 128,
101 };
102 assert!(matches!(
103 err,
104 HttpError::BufferTooSmall {
105 needed: 512,
106 available: 128,
107 }
108 ));
109 assert_eq!(
110 err.to_string(),
111 "write buffer too small: need 512 bytes, have 128"
112 );
113 }
114
115 #[test]
116 fn http_error_invalid_header_value() {
117 let err = HttpError::InvalidHeaderValue;
118 assert!(matches!(err, HttpError::InvalidHeaderValue));
119 assert_eq!(err.to_string(), "header name or value contains CR/LF");
120 }
121
122 #[test]
123 fn http_error_eq() {
124 assert_eq!(HttpError::TooManyHeaders, HttpError::TooManyHeaders);
125 assert_ne!(HttpError::TooManyHeaders, HttpError::InvalidHeaderValue);
126 assert_eq!(
127 HttpError::HeadTooLarge { max: 100 },
128 HttpError::HeadTooLarge { max: 100 }
129 );
130 }
131}