aep-core 0.1.0

Transport-independent protocol primitives for the Agent Enrollment Protocol.
Documentation
use async_trait::async_trait;
use http::{HeaderMap, Method, StatusCode};
use std::error::Error as StdError;

use thiserror::Error;
use url::Url;

#[derive(Clone, Debug)]
pub struct HttpRequest {
    pub method: Method,
    pub url: Url,
    pub headers: HeaderMap,
    pub body: Vec<u8>,
}

#[derive(Clone, Debug)]
pub struct HttpResponse {
    pub status: StatusCode,
    pub final_url: Url,
    pub headers: HeaderMap,
    pub body: Vec<u8>,
}

#[derive(Debug, Error)]
#[error("{message}")]
pub struct TransportError {
    message: String,
    #[source]
    source: Option<Box<dyn StdError + Send + Sync>>,
}

impl TransportError {
    pub fn new(message: impl Into<String>) -> Self {
        Self {
            message: message.into(),
            source: None,
        }
    }

    pub fn with_source(
        message: impl Into<String>,
        source: impl StdError + Send + Sync + 'static,
    ) -> Self {
        Self {
            message: message.into(),
            source: Some(Box::new(source)),
        }
    }
}

#[async_trait]
pub trait HttpTransport: Send + Sync {
    async fn send(&self, request: HttpRequest) -> Result<HttpResponse, TransportError>;
}

#[cfg(test)]
mod tests {
    use std::fmt;

    use super::*;

    #[derive(Debug)]
    struct ExampleError;

    impl fmt::Display for ExampleError {
        fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
            formatter.write_str("cause")
        }
    }

    impl StdError for ExampleError {}

    #[test]
    fn preserves_transport_error_context() {
        assert_eq!(
            TransportError::new("request failed").to_string(),
            "request failed"
        );
        let error = TransportError::with_source("request failed", ExampleError);
        assert_eq!(error.to_string(), "request failed");
        assert_eq!(
            StdError::source(&error).map(ToString::to_string),
            Some("cause".to_owned())
        );
    }
}