rust_fetch/
network_error.rs

1use std::{fmt::Display, net::SocketAddr};
2
3use bytes::Bytes;
4use reqwest::{Response, StatusCode};
5use thiserror::Error;
6
7/// Represents any non-200 HTTP status code
8///
9/// # Example
10/// ```rust
11/// use httpmock::prelude::*;
12/// use rust_fetch::Fetch;
13///
14/// #[tokio::main]
15/// async fn main() {
16///     let server = MockServer::start();
17///     let fetch = Fetch::new(&server.base_url(), None).unwrap();
18///
19///     server.mock(|when, then| {
20///         when.path("/test").method(GET);
21///         then.status(400);
22///     });
23///
24///     let response = fetch.get::<()>("/test", None).await;
25///
26///     if let Err(rust_fetch::FetchError::NetworkError(ref err)) = response {
27///         assert_eq!(400, err.status_code);
28///         assert_eq!(Some(*server.address()), err.origin_address);
29///         assert_eq!(false, err.raw_body.is_none());
30///     } else {
31///         panic!("Result was not an instance of NetworkError");
32///     }
33///
34///     assert!(response.is_err());
35/// }
36/// ```
37#[derive(Error, Debug)]
38pub struct NetworkError {
39    pub status_code: StatusCode,
40    pub origin_address: Option<SocketAddr>,
41    pub raw_body: Option<Bytes>,
42}
43
44impl Display for NetworkError {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        let body = self
47            .raw_body
48            .as_ref()
49            .map(|val| String::from_utf8(val.to_owned().to_vec()).ok())
50            .unwrap_or_default()
51            .unwrap_or_default();
52
53        write!(
54            f,
55            "Error -- Status: {}, Origin: {}, Body: {}",
56            self.status_code,
57            self.origin_address
58                .map(|socket| socket.to_string())
59                .unwrap_or_default(),
60            body
61        )
62    }
63}
64
65impl NetworkError {
66    pub async fn new(response: Response) -> Self {
67        Self {
68            status_code: response.status(),
69            origin_address: response.remote_addr(),
70            raw_body: response.bytes().await.ok(),
71        }
72    }
73}