sms_client/http/
error.rs

1//! HTTP interface related errors.
2
3/// An error originating from the SMS HttpClient.
4#[derive(thiserror::Error, Debug)]
5pub enum HttpError {
6
7    /// Network request failed (connection issues, timeouts, etc.)
8    #[error("Network request failed: {0}")]
9    RequestError(#[from] reqwest::Error),
10
11    /// Failed to parse the provided URL.
12    #[error("Invalid URL: {0}")]
13    UrlParseError(#[from] url::ParseError),
14
15    /// Failed to parse JSON response from the API.
16    #[error("JSON parsing failed: {0}")]
17    JsonError(#[from] serde_json::Error),
18
19    /// HTTP request returned a non-success status code.
20    #[error("{}", HttpError::format_http_error(.status, &.message))]
21    HttpStatus {
22        /// HTTP status returned in response.
23        status: u16,
24        /// Full response body as text.
25        message: String
26    },
27
28    /// API returned success=false with an error message.
29    #[error("API responded with success=false: {message}")]
30    ApiError {
31        /// The error_message key from response.
32        message: String
33    },
34
35    /// API response missing the expected 'response' field.
36    #[error("Missing 'response' field in API response")]
37    MissingResponseField,
38
39    /// Modem response missing the expected 'type' field.
40    #[error("Missing 'type' field in API response")]
41    MissingTypeField,
42
43    /// Modem response missing the expected 'data' field.
44    #[error("Missing 'data' field in API response")]
45    MissingDataField,
46
47    /// Modem response type doesn't match what was expected.
48    #[error("Type mismatch: expected '{expected}', got '{actual}'")]
49    ResponseTypeMismatch {
50        /// The expected response data-type.
51        expected: String,
52        /// The actual response data-type.
53        actual: String
54    }
55}
56impl HttpError {
57    fn status_text(status: u16) -> &'static str {
58        match status {
59            200 => "OK",
60            400 => "Bad Request",
61            401 => "Unauthorized",
62            403 => "Forbidden",
63            404 => "Not Found",
64            405 => "Method Not Allowed",
65            408 => "Not Acceptable",
66            429 => "Too Many Requests",
67            500 => "Internal Server Error",
68            503 => "Service Unavailable",
69            504 => "Gateway Timeout",
70            _ => "Unknown"
71        }
72    }
73
74    fn format_http_error(status: &u16, message: &str) -> String {
75        if message.trim().is_empty() {
76            format!("HTTP {status} {}", Self::status_text(*status))
77        } else {
78            format!("HTTP {status}: {}", message)
79        }
80    }
81}
82
83/// Result type alias for HTTP operations.
84pub type HttpResult<T> = Result<T, HttpError>;