Skip to main content

cdk_http_client/
response.rs

1//! HTTP response types
2
3use serde::de::DeserializeOwned;
4
5use crate::error::HttpError;
6
7/// HTTP Response type - generic over the body type R and error type E
8/// This is the primary return type for all HTTP operations
9pub type Response<R, E = HttpError> = Result<R, E>;
10
11/// Raw HTTP response with status code and body access
12#[derive(Debug)]
13pub struct RawResponse {
14    status: u16,
15    inner: reqwest::Response,
16}
17
18impl RawResponse {
19    /// Create a new RawResponse from a reqwest::Response
20    pub(crate) fn new(response: reqwest::Response) -> Self {
21        Self {
22            status: response.status().as_u16(),
23            inner: response,
24        }
25    }
26
27    /// Get the HTTP status code
28    pub fn status(&self) -> u16 {
29        self.status
30    }
31
32    /// Check if the response status is a success (2xx)
33    pub fn is_success(&self) -> bool {
34        (200..300).contains(&self.status)
35    }
36
37    /// Check if the response status is a client error (4xx)
38    pub fn is_client_error(&self) -> bool {
39        (400..500).contains(&self.status)
40    }
41
42    /// Check if the response status is a server error (5xx)
43    pub fn is_server_error(&self) -> bool {
44        (500..600).contains(&self.status)
45    }
46
47    /// Get the response body as text
48    pub async fn text(self) -> Response<String> {
49        self.inner.text().await.map_err(HttpError::from)
50    }
51
52    /// Get the response body as JSON
53    pub async fn json<T: DeserializeOwned>(self) -> Response<T> {
54        self.inner.json().await.map_err(HttpError::from)
55    }
56
57    /// Get the response body as bytes
58    pub async fn bytes(self) -> Response<Vec<u8>> {
59        self.inner
60            .bytes()
61            .await
62            .map(|b| b.to_vec())
63            .map_err(HttpError::from)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    // Note: RawResponse tests require a real reqwest::Response,
72    // so they are in tests/integration.rs using mockito.
73
74    #[test]
75    fn test_response_type_is_result() {
76        // Response<R, E> is just a type alias for Result<R, E>
77        let success: Response<i32> = Ok(42);
78        assert!(success.is_ok());
79        assert!(matches!(success, Ok(42)));
80
81        let error: Response<i32> = Err(HttpError::Timeout);
82        assert!(error.is_err());
83        assert!(matches!(error, Err(HttpError::Timeout)));
84    }
85}