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}