Skip to main content

praxis_core/
errors.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2024 Praxis Contributors
3
4//! Shared error types for the Praxis workspace.
5//!
6//! [`ProxyError`] is the primary error type, re-exported from `praxis_core`.
7
8use thiserror::Error;
9
10// -----------------------------------------------------------------------------
11// Errors
12// -----------------------------------------------------------------------------
13
14/// Errors that can occur during proxy operation.
15///
16/// ```
17/// use praxis_core::ProxyError;
18///
19/// let e = ProxyError::Config("bad yaml".into());
20/// assert_eq!(e.to_string(), "config: bad yaml");
21///
22/// let e = ProxyError::NoRoute("GET /missing".into());
23/// assert_eq!(e.to_string(), "no route for GET /missing");
24///
25/// let e = ProxyError::NoUpstream("backend".into());
26/// assert_eq!(e.to_string(), "no upstream in cluster 'backend'");
27/// ```
28#[derive(Debug, Error)]
29pub enum ProxyError {
30    /// Configuration loading or validation error.
31    ///
32    /// Raised during startup or hot-reload when YAML parsing or
33    /// validation fails. Not retriable; fix the configuration.
34    /// The server continues running with the previous config on
35    /// hot-reload failures.
36    #[error("config: {0}")]
37    Config(String),
38
39    /// No route matched the incoming request.
40    ///
41    /// Raised during request routing when no filter chain's
42    /// router matches the method, path, and headers. Returns
43    /// 404 to the client. Not retriable for the same request.
44    #[error("no route for {0}")]
45    NoRoute(String),
46
47    /// No upstream available in the given cluster.
48    ///
49    /// Raised when a route matched but all endpoints in the
50    /// target cluster are unhealthy or the cluster is empty.
51    /// Returns 503 to the client. Retriable after health checks
52    /// recover an endpoint.
53    #[error("no upstream in cluster '{0}'")]
54    NoUpstream(String),
55}
56
57// -----------------------------------------------------------------------------
58// Tests
59// -----------------------------------------------------------------------------
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn error_display() {
67        let e = ProxyError::Config("bad yaml".into());
68        assert_eq!(e.to_string(), "config: bad yaml", "Config error display mismatch");
69
70        let e = ProxyError::NoRoute("GET /missing".into());
71        assert_eq!(
72            e.to_string(),
73            "no route for GET /missing",
74            "NoRoute error display mismatch"
75        );
76
77        let e = ProxyError::NoUpstream("backend".into());
78        assert_eq!(
79            e.to_string(),
80            "no upstream in cluster 'backend'",
81            "NoUpstream error display mismatch"
82        );
83    }
84}