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 {
44 name: name.into()
45 }
46 }
47
48 pub fn invalid_header_value<T: Into<String>>(value: T) -> Self {
50 ParseError::InvalidHeaderValue {
51 value: value.into()
52 }
53 }
54
55 pub fn header_to_str_error() -> Self {
57 ParseError::HeaderToStrError
58 }
59
60 pub fn invalid_status_code(code: u16) -> Self {
62 ParseError::InvalidStatusCode { code }
63 }
64
65 pub fn json_rejection<T: Into<String>>(message: T) -> Self {
67 ParseError::JsonRejection {
68 message: message.into()
69 }
70 }
71}
72
73impl From<axum::http::method::InvalidMethod> for ParseError {
75 fn from(err: axum::http::method::InvalidMethod) -> Self {
76 ParseError::InvalidMethod {
77 method: err.to_string()
78 }
79 }
80}
81
82impl From<axum::http::header::InvalidHeaderName> for ParseError {
83 fn from(err: axum::http::header::InvalidHeaderName) -> Self {
84 ParseError::InvalidHeaderName {
85 name: err.to_string()
86 }
87 }
88}
89
90impl From<axum::http::header::InvalidHeaderValue> for ParseError {
91 fn from(err: axum::http::header::InvalidHeaderValue) -> Self {
92 ParseError::InvalidHeaderValue {
93 value: err.to_string()
94 }
95 }
96}
97
98impl From<axum::http::header::ToStrError> for ParseError {
99 fn from(_: axum::http::header::ToStrError) -> Self {
100 ParseError::HeaderToStrError
101 }
102}
103
104impl From<axum::extract::rejection::JsonRejection> for ParseError {
108 fn from(err: axum::extract::rejection::JsonRejection) -> Self {
109 ParseError::JsonRejection {
110 message: err.to_string()
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_parse_error_creation() {
121 let error = ParseError::invalid_method("INVALID");
122 assert!(matches!(error, ParseError::InvalidMethod { .. }));
123 assert_eq!(error.to_string(), "Invalid HTTP method: INVALID");
124 }
125
126 #[test]
127 fn test_header_errors() {
128 let name_error = ParseError::invalid_header_name("bad name");
129 let value_error = ParseError::invalid_header_value("bad\x00value");
130 let str_error = ParseError::header_to_str_error();
131
132 assert!(matches!(name_error, ParseError::InvalidHeaderName { .. }));
133 assert!(matches!(value_error, ParseError::InvalidHeaderValue { .. }));
134 assert!(matches!(str_error, ParseError::HeaderToStrError));
135 }
136
137 #[test]
138 fn test_status_code_error() {
139 let error = ParseError::invalid_status_code(999);
140 assert!(matches!(error, ParseError::InvalidStatusCode { code: 999 }));
141 }
142
143 #[test]
144 fn test_json_error() {
145 let error = ParseError::json_rejection("Invalid JSON syntax");
146 assert!(matches!(error, ParseError::JsonRejection { .. }));
147 }
148
149 #[test]
150 fn test_axum_conversions() {
151 let axum_method_err = axum::http::Method::from_bytes(b"INVALID METHOD WITH SPACES").unwrap_err();
153 let parse_err: ParseError = axum_method_err.into();
154 assert!(matches!(parse_err, ParseError::InvalidMethod { .. }));
155 }
156}