Skip to main content

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 {}