Skip to main content

cdk_http_client/
error.rs

1//! HTTP error types
2
3use thiserror::Error;
4
5/// HTTP errors that can occur during requests
6#[derive(Debug, Error)]
7pub enum HttpError {
8    /// HTTP error with status code
9    #[error("HTTP error ({status}): {message}")]
10    Status {
11        /// HTTP status code
12        status: u16,
13        /// Error message
14        message: String,
15    },
16    /// Connection error
17    #[error("Connection error: {0}")]
18    Connection(String),
19    /// Request timeout
20    #[error("Request timeout")]
21    Timeout,
22    /// Serialization error
23    #[error("Serialization error: {0}")]
24    Serialization(String),
25    /// Proxy error
26    #[error("Proxy error: {0}")]
27    Proxy(String),
28    /// Client build error
29    #[error("Client build error: {0}")]
30    Build(String),
31    /// Other error
32    #[error("{0}")]
33    Other(String),
34}
35
36impl From<reqwest::Error> for HttpError {
37    fn from(err: reqwest::Error) -> Self {
38        if err.is_timeout() {
39            HttpError::Timeout
40        } else if err.is_builder() {
41            HttpError::Build(err.to_string())
42        } else if let Some(status) = err.status() {
43            HttpError::Status {
44                status: status.as_u16(),
45                message: err.to_string(),
46            }
47        } else {
48            // is_connect() is not available on wasm32
49            #[cfg(not(target_arch = "wasm32"))]
50            if err.is_connect() {
51                return HttpError::Connection(err.to_string());
52            }
53            HttpError::Other(err.to_string())
54        }
55    }
56}
57
58impl From<serde_json::Error> for HttpError {
59    fn from(err: serde_json::Error) -> Self {
60        HttpError::Serialization(err.to_string())
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_http_error_status_display() {
70        let error = HttpError::Status {
71            status: 404,
72            message: "Not Found".to_string(),
73        };
74        assert_eq!(format!("{}", error), "HTTP error (404): Not Found");
75    }
76
77    #[test]
78    fn test_http_error_connection_display() {
79        let error = HttpError::Connection("connection refused".to_string());
80        assert_eq!(format!("{}", error), "Connection error: connection refused");
81    }
82
83    #[test]
84    fn test_http_error_timeout_display() {
85        let error = HttpError::Timeout;
86        assert_eq!(format!("{}", error), "Request timeout");
87    }
88
89    #[test]
90    fn test_http_error_serialization_display() {
91        let error = HttpError::Serialization("invalid JSON".to_string());
92        assert_eq!(format!("{}", error), "Serialization error: invalid JSON");
93    }
94
95    #[test]
96    fn test_http_error_proxy_display() {
97        let error = HttpError::Proxy("proxy unreachable".to_string());
98        assert_eq!(format!("{}", error), "Proxy error: proxy unreachable");
99    }
100
101    #[test]
102    fn test_http_error_build_display() {
103        let error = HttpError::Build("invalid config".to_string());
104        assert_eq!(format!("{}", error), "Client build error: invalid config");
105    }
106
107    #[test]
108    fn test_http_error_other_display() {
109        let error = HttpError::Other("unknown error".to_string());
110        assert_eq!(format!("{}", error), "unknown error");
111    }
112
113    #[test]
114    fn test_from_serde_json_error() {
115        // Create an invalid JSON parse to get a serde_json::Error
116        let result: Result<String, _> = serde_json::from_str("not valid json");
117        let json_error = result.expect_err("Invalid JSON should produce an error");
118        let http_error: HttpError = json_error.into();
119
120        match http_error {
121            HttpError::Serialization(msg) => {
122                assert!(
123                    msg.contains("expected"),
124                    "Error message should describe JSON error"
125                );
126            }
127            _ => panic!("Expected HttpError::Serialization"),
128        }
129    }
130}