elif_http/errors/
parse_error.rs1use thiserror::Error;
7
8pub type ParseResult<T> = Result<T, ParseError>;
10
11#[derive(Error, Debug)]
13pub enum ParseError {
14 #[error("Invalid HTTP method: {method}")]
15 InvalidMethod { method: String },
16
17 #[error("Invalid header name: {name}")]
18 InvalidHeaderName { name: String },
19
20 #[error("Invalid header value: {value}")]
21 InvalidHeaderValue { value: String },
22
23 #[error("Header value contains non-ASCII characters")]
24 HeaderToStrError,
25
26 #[error("Invalid status code: {code}")]
27 InvalidStatusCode { code: u16 },
28
29 #[error("JSON parsing failed: {message}")]
30 JsonRejection { message: String },
31}
32
33impl ParseError {
34 pub fn invalid_method<T: Into<String>>(method: T) -> Self {
36 ParseError::InvalidMethod {
37 method: method.into(),
38 }
39 }
40
41 pub fn invalid_header_name<T: Into<String>>(name: T) -> Self {
43 ParseError::InvalidHeaderName { name: name.into() }
44 }
45
46 pub fn invalid_header_value<T: Into<String>>(value: T) -> Self {
48 ParseError::InvalidHeaderValue {
49 value: value.into(),
50 }
51 }
52
53 pub fn header_to_str_error() -> Self {
55 ParseError::HeaderToStrError
56 }
57
58 pub fn invalid_status_code(code: u16) -> Self {
60 ParseError::InvalidStatusCode { code }
61 }
62
63 pub fn json_rejection<T: Into<String>>(message: T) -> Self {
65 ParseError::JsonRejection {
66 message: message.into(),
67 }
68 }
69}
70
71impl From<axum::http::method::InvalidMethod> for ParseError {
73 fn from(err: axum::http::method::InvalidMethod) -> Self {
74 ParseError::InvalidMethod {
75 method: err.to_string(),
76 }
77 }
78}
79
80impl From<axum::http::header::InvalidHeaderName> for ParseError {
81 fn from(err: axum::http::header::InvalidHeaderName) -> Self {
82 ParseError::InvalidHeaderName {
83 name: err.to_string(),
84 }
85 }
86}
87
88impl From<axum::http::header::InvalidHeaderValue> for ParseError {
89 fn from(err: axum::http::header::InvalidHeaderValue) -> Self {
90 ParseError::InvalidHeaderValue {
91 value: err.to_string(),
92 }
93 }
94}
95
96impl From<axum::http::header::ToStrError> for ParseError {
97 fn from(_: axum::http::header::ToStrError) -> Self {
98 ParseError::HeaderToStrError
99 }
100}
101
102impl From<axum::extract::rejection::JsonRejection> for ParseError {
106 fn from(err: axum::extract::rejection::JsonRejection) -> Self {
107 ParseError::JsonRejection {
108 message: err.to_string(),
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_parse_error_creation() {
119 let error = ParseError::invalid_method("INVALID");
120 assert!(matches!(error, ParseError::InvalidMethod { .. }));
121 assert_eq!(error.to_string(), "Invalid HTTP method: INVALID");
122 }
123
124 #[test]
125 fn test_header_errors() {
126 let name_error = ParseError::invalid_header_name("bad name");
127 let value_error = ParseError::invalid_header_value("bad\x00value");
128 let str_error = ParseError::header_to_str_error();
129
130 assert!(matches!(name_error, ParseError::InvalidHeaderName { .. }));
131 assert!(matches!(value_error, ParseError::InvalidHeaderValue { .. }));
132 assert!(matches!(str_error, ParseError::HeaderToStrError));
133 }
134
135 #[test]
136 fn test_status_code_error() {
137 let error = ParseError::invalid_status_code(999);
138 assert!(matches!(error, ParseError::InvalidStatusCode { code: 999 }));
139 }
140
141 #[test]
142 fn test_json_error() {
143 let error = ParseError::json_rejection("Invalid JSON syntax");
144 assert!(matches!(error, ParseError::JsonRejection { .. }));
145 }
146
147 #[test]
148 fn test_axum_conversions() {
149 let axum_method_err =
151 axum::http::Method::from_bytes(b"INVALID METHOD WITH SPACES").unwrap_err();
152 let parse_err: ParseError = axum_method_err.into();
153 assert!(matches!(parse_err, ParseError::InvalidMethod { .. }));
154 }
155}