ferrijs_fetch/error.rs
1//! Typed error for the fetch engine.
2//!
3//! The WHATWG binding layer distinguishes an abort (→ `AbortError`) from
4//! a generic network failure (→ `TypeError "Failed to fetch"`), so the
5//! engine returns a categorized error rather than a flat string.
6
7use std::fmt;
8
9/// A fetch engine failure.
10#[derive(Debug)]
11pub enum FetchError {
12 /// A transport failure (connection refused, reset past the retry
13 /// budget, TLS error, DNS). WHATWG surfaces this as `TypeError`.
14 Network(String),
15 /// The request's `AbortSignal` fired.
16 Abort(String),
17 /// The per-request timeout elapsed.
18 Timeout(String),
19 /// `redirect: follow` exceeded the redirect budget.
20 TooManyRedirects(u32),
21 /// `redirect: error` saw a 3xx, or a redirect target had no `Location`
22 /// that could be resolved.
23 RedirectRefused(String),
24 /// The sandbox network guard denied the URL or a resolved address.
25 Blocked(String),
26 /// The realm's `net` grant refused the host. Kept typed so a runtime
27 /// can throw it as the permission error it is.
28 Denied(ferrijs_permissions::Denied),
29 /// A URL could not be parsed / resolved against the base URL.
30 InvalidUrl(String),
31 /// The response body could not be read.
32 Body(String),
33 /// The host-owned cookie jar or defaults could not be read or written
34 /// (see [`crate::ContextBridge`]).
35 Bridge(String),
36}
37
38impl fmt::Display for FetchError {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 Self::Network(m)
42 | Self::Abort(m)
43 | Self::Timeout(m)
44 | Self::RedirectRefused(m)
45 | Self::Blocked(m)
46 | Self::InvalidUrl(m)
47 | Self::Body(m)
48 | Self::Bridge(m) => f.write_str(m),
49 Self::TooManyRedirects(max) => write!(f, "too many redirects (max {max})"),
50 Self::Denied(d) => d.fmt(f),
51 }
52 }
53}
54
55impl From<crate::net_guard::GuardError> for FetchError {
56 fn from(e: crate::net_guard::GuardError) -> Self {
57 match e {
58 crate::net_guard::GuardError::Denied(d) => Self::Denied(d),
59 other => Self::Blocked(other.to_string()),
60 }
61 }
62}
63
64impl std::error::Error for FetchError {}