Skip to main content

aep_core/
transport.rs

1use async_trait::async_trait;
2use http::{HeaderMap, Method, StatusCode};
3use std::error::Error as StdError;
4
5use thiserror::Error;
6use url::Url;
7
8#[derive(Clone, Debug)]
9pub struct HttpRequest {
10    pub method: Method,
11    pub url: Url,
12    pub headers: HeaderMap,
13    pub body: Vec<u8>,
14}
15
16#[derive(Clone, Debug)]
17pub struct HttpResponse {
18    pub status: StatusCode,
19    pub final_url: Url,
20    pub headers: HeaderMap,
21    pub body: Vec<u8>,
22}
23
24#[derive(Debug, Error)]
25#[error("{message}")]
26pub struct TransportError {
27    message: String,
28    #[source]
29    source: Option<Box<dyn StdError + Send + Sync>>,
30}
31
32impl TransportError {
33    pub fn new(message: impl Into<String>) -> Self {
34        Self {
35            message: message.into(),
36            source: None,
37        }
38    }
39
40    pub fn with_source(
41        message: impl Into<String>,
42        source: impl StdError + Send + Sync + 'static,
43    ) -> Self {
44        Self {
45            message: message.into(),
46            source: Some(Box::new(source)),
47        }
48    }
49}
50
51#[async_trait]
52pub trait HttpTransport: Send + Sync {
53    async fn send(&self, request: HttpRequest) -> Result<HttpResponse, TransportError>;
54}
55
56#[cfg(test)]
57mod tests {
58    use std::fmt;
59
60    use super::*;
61
62    #[derive(Debug)]
63    struct ExampleError;
64
65    impl fmt::Display for ExampleError {
66        fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
67            formatter.write_str("cause")
68        }
69    }
70
71    impl StdError for ExampleError {}
72
73    #[test]
74    fn preserves_transport_error_context() {
75        assert_eq!(
76            TransportError::new("request failed").to_string(),
77            "request failed"
78        );
79        let error = TransportError::with_source("request failed", ExampleError);
80        assert_eq!(error.to_string(), "request failed");
81        assert_eq!(
82            StdError::source(&error).map(ToString::to_string),
83            Some("cause".to_owned())
84        );
85    }
86}