#[non_exhaustive]pub enum HttpError {
Network(Error),
RedirectDenied {
source_key: String,
host: String,
expected_hosts: Vec<String>,
},
InsecureRedirect {
scheme: String,
},
OversizedBody {
actual: u64,
cap: u64,
},
NotAPdf {
got: [u8; 5],
},
HttpStatus {
status: u16,
url: String,
},
UnknownSource {
source_key: String,
},
InvalidHeader {
name: String,
reason: String,
},
}Expand description
Errors that can arise during HTTP fetches.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Network(Error)
Transport / DNS / TLS failure or other reqwest-level error. Note
that reqwest surfaces a redirect-policy abort (via Attempt::error)
as a reqwest::Error carrying the source error — callers seeing
Network for what they believed was a redirect violation should
inspect the inner error chain.
RedirectDenied
Redirect target host did not match any pattern in the source’s
redirect_hosts. See docs/REDIRECT_ALLOWLIST.md §2.2.
Field naming: source_key rather than source because thiserror
auto-treats a field literally named source as a #[source] error
chain link (which would require the field to implement std::error::Error).
expected_hosts carries a snapshot of the source’s allowlist
patterns at the time of the denial — populated for the structured
denial_context.expected channel introduced by ADR-0023 §4
(NORMATIVE mapping table). Cloning the patterns into the error
keeps the From<&HttpError> for Option<DenialContext> impl from
having to re-look-up the allowlist by source_key. May be empty
when the rejection happened before any allowlist was matched
(e.g. URL had no host component at all).
Fields
InsecureRedirect
Redirect target had a scheme other than https. See
docs/SECURITY.md §1.3.
OversizedBody
Body would exceed PDF_MAX_BYTES either by a Content-Length
hint or by accumulated streamed bytes. See docs/SECURITY.md §1.2.
Fields
cap: u64Hard upper bound (always PDF_MAX_BYTES).
NotAPdf
PDF magic-byte mismatch — the body does not start with %PDF-.
We deliberately do NOT use Content-Type (publishers misbehave —
the magic byte is the trustworthy signal per docs/SECURITY.md
§1.2 “Magic-byte mismatch” row).
HttpStatus
Server returned a non-2xx status.
UnknownSource
No allowlist entry exists for this source. The caller asked
HttpClient to fetch on behalf of a source that wasn’t passed to
HttpClient::new.
See note on RedirectDenied for why the field is source_key.
InvalidHeader
A header name or value passed to
HttpClient::fetch_bytes_with_headers was not a valid HTTP
header. The header parser only accepts the visible-ASCII subset
per RFC 7230 §3.2; control characters and non-ASCII bytes are
rejected before the request is even built. Surfaces as
ErrorCode::InternalError at the public boundary (callers
supplying bad headers are responsible for fixing the call site;
not a denial in the ADR-0023 sense).
Trait Implementations§
Source§impl Error for HttpError
impl Error for HttpError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<&HttpError> for Option<DenialContext>
Map an HttpError reference to the structured crate::DenialContext
channel introduced by ADR-0023.
impl From<&HttpError> for Option<DenialContext>
Map an HttpError reference to the structured crate::DenialContext
channel introduced by ADR-0023.
Returns Some(_) for the four denial classes named in ADR-0023 §4
(RedirectDenied, OversizedBody, NotAPdf, InsecureRedirect) and
None for every other variant — Network, HttpStatus,
UnknownSource are not denials in the ADR-0023 sense (they are
transport / upstream / programming-error signals, not allowlist or
cap rejections).
The &HttpError borrow form is used (rather than HttpError) so the
caller — typically the orchestrator that already needs the original
error for error.message and the From<HttpError> for ErrorCode
collapse — does not have to clone the error to produce the optional
structured side-channel.