Skip to main content

gatel_core/
lib.rs

1pub mod admin;
2mod cache_control;
3pub mod config;
4mod crypto;
5mod encoding;
6pub mod events;
7mod glob;
8pub mod goals;
9pub mod hoops;
10pub mod observability;
11mod placeholder;
12pub mod plugin;
13pub mod proxy;
14pub mod router;
15pub mod runtime;
16pub mod salvo_service;
17pub mod sd_notify;
18pub mod server;
19pub mod storage;
20pub mod stream;
21pub mod tls;
22pub mod ttl_cache;
23mod websocket;
24
25use bytes::Bytes;
26use http_body_util::BodyExt;
27use http_body_util::combinators::BoxBody;
28
29/// The body type used throughout gatel — error is a boxed trait object
30/// so we can unify bodies from different sources (hyper Incoming, Full, Empty, upstream).
31pub type Body = BoxBody<Bytes, BoxError>;
32
33/// Boxed error type alias.
34pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
35
36/// Create an empty body.
37pub fn empty_body() -> Body {
38    use http_body_util::Empty;
39    BoxBody::new(
40        Empty::new().map_err(|never: std::convert::Infallible| -> BoxError { match never {} }),
41    )
42}
43
44/// Create a body from bytes.
45pub fn full_body(data: impl Into<Bytes>) -> Body {
46    use http_body_util::Full;
47    BoxBody::new(
48        Full::new(data.into())
49            .map_err(|never: std::convert::Infallible| -> BoxError { match never {} }),
50    )
51}
52
53/// Top-level error type for the proxy.
54#[derive(Debug, thiserror::Error)]
55pub enum ProxyError {
56    #[error("hyper error: {0}")]
57    Hyper(#[from] hyper::Error),
58
59    #[error("HTTP error: {0}")]
60    Http(#[from] http::Error),
61
62    #[error("hyper-util client error: {0}")]
63    Client(#[from] hyper_util::client::legacy::Error),
64
65    #[error("IO error: {0}")]
66    Io(#[from] std::io::Error),
67
68    #[error("config error: {0}")]
69    Config(#[from] config::ConfigError),
70
71    #[error("no upstream available")]
72    NoUpstream,
73
74    #[error("bad request: {0}")]
75    BadRequest(String),
76
77    #[error("{0}")]
78    Internal(String),
79}
80
81impl ProxyError {
82    /// Convert this error into an HTTP response.
83    pub fn into_response(self) -> http::Response<Body> {
84        let status = match &self {
85            ProxyError::BadRequest(_) => http::StatusCode::BAD_REQUEST,
86            ProxyError::NoUpstream => http::StatusCode::BAD_GATEWAY,
87            _ => http::StatusCode::INTERNAL_SERVER_ERROR,
88        };
89        let body = full_body(self.to_string());
90        http::Response::builder().status(status).body(body).unwrap()
91    }
92}