Skip to main content

soma_openapi/
error.rs

1#[derive(Debug, Clone, thiserror::Error)]
2pub enum SsrfError {
3    #[error("{0}")]
4    InvalidUrl(String),
5    #[error("{0}")]
6    Blocked(String),
7}
8
9impl SsrfError {
10    #[must_use]
11    pub fn kind(&self) -> &'static str {
12        match self {
13            Self::InvalidUrl(_) => "invalid_param",
14            Self::Blocked(_) => "ssrf_blocked",
15        }
16    }
17}
18
19#[derive(Debug, Clone, thiserror::Error)]
20pub enum OpenApiError {
21    #[error("spec `{label}` base URL rejected by SSRF guard: {reason}")]
22    SsrfRejected { label: String, reason: String },
23    #[error("failed to parse OpenAPI spec `{label}`")]
24    SpecParse { label: String },
25    #[error("spec document `{label}` exceeds the size cap")]
26    SpecTooLarge { label: String },
27    #[error("unknown spec label `{label}`")]
28    UnknownInstance { label: String, valid: Vec<String> },
29    #[error("unknown operation `{operation_id}` in spec `{label}`")]
30    UnknownOperation { label: String, operation_id: String },
31    #[error("request for spec `{label}` blocked: resolved to a private address")]
32    RequestBlockedPrivateAddr { label: String },
33    #[error("could not resolve host for spec `{label}`")]
34    ResolveFailed { label: String },
35    #[error("operation `{label}` path parameter `{param}` is missing or invalid")]
36    InvalidPathParam { label: String, param: String },
37    #[error("failed to build hardened HTTP client")]
38    ClientBuildFailed,
39    #[error("upstream request for spec `{label}` failed")]
40    UpstreamRequest { label: String },
41    #[error("upstream request for spec `{label}` timed out")]
42    UpstreamTimeout { label: String },
43}
44
45impl OpenApiError {
46    #[must_use]
47    pub fn kind(&self) -> &'static str {
48        match self {
49            Self::SsrfRejected { .. } | Self::SpecParse { .. } | Self::SpecTooLarge { .. } => {
50                "config_error"
51            }
52            Self::RequestBlockedPrivateAddr { .. } => "forbidden",
53            Self::InvalidPathParam { .. } => "invalid_param",
54            Self::UnknownInstance { .. } => "unknown_instance",
55            Self::UnknownOperation { .. } => "unknown_action",
56            Self::ResolveFailed { .. } | Self::ClientBuildFailed | Self::UpstreamRequest { .. } => {
57                "internal_error"
58            }
59            Self::UpstreamTimeout { .. } => "timeout",
60        }
61    }
62}