clawhdf5-remote: redirects are followed safely
ureq's defaults followed up to 10 redirects, including from https to plain http, and forwarded the custom HttpOptions::headers (X-Api-Key, Cookie, ...) to whatever host a redirect named — only Authorization was stripped. HttpStorage now follows redirects itself (ureq's max_redirects is 0): - at most HttpOptions::max_redirects per request (default 5; 0 refuses any redirect), then RemoteError::Redirect; - never from https to another scheme, nor to a non-http(s) URL; - once a redirect leaves the URL's origin (scheme, host, port), none of the custom headers is sent any more (Authorization included); - each hop counts as a request; errors show the target redacted. Tests: a redirect to another local port reads the right data and the target never sees X-Api-Key or Authorization (it did before); a same-origin redirect keeps them; a loop stops after 6 requests; 0 refuses; unit tests for target resolution, the https downgrade and origins. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -158,6 +158,10 @@ pub enum RemoteError {
|
||||
ObjectStore(String),
|
||||
/// Called in a way the backend cannot serve.
|
||||
Usage(String),
|
||||
/// A redirect that is not followed: from `https` to `http`, to
|
||||
/// another scheme, or beyond
|
||||
/// [`HttpOptions::max_redirects`](crate::HttpOptions).
|
||||
Redirect(String),
|
||||
/// The file is larger than a download was allowed to be
|
||||
/// ([`download`](crate::download)).
|
||||
TooLarge {
|
||||
@@ -189,6 +193,7 @@ impl RemoteError {
|
||||
RemoteError::Transport(s) => RemoteError::Transport(f(s)),
|
||||
RemoteError::ObjectStore(s) => RemoteError::ObjectStore(f(s)),
|
||||
RemoteError::Usage(s) => RemoteError::Usage(f(s)),
|
||||
RemoteError::Redirect(s) => RemoteError::Redirect(f(s)),
|
||||
e @ RemoteError::TooLarge { .. } => e,
|
||||
RemoteError::Backend(s) => RemoteError::Backend(f(s)),
|
||||
}
|
||||
@@ -221,6 +226,7 @@ impl std::fmt::Display for RemoteError {
|
||||
RemoteError::Transport(s) => write!(f, "network error: {s}"),
|
||||
RemoteError::ObjectStore(s) => write!(f, "object store: {s}"),
|
||||
RemoteError::Usage(s) => write!(f, "{s}"),
|
||||
RemoteError::Redirect(s) => write!(f, "redirect refused: {s}"),
|
||||
RemoteError::TooLarge { len, limit } => write!(
|
||||
f,
|
||||
"the remote file is {len} bytes, more than the download limit of {limit} bytes"
|
||||
|
||||
Reference in New Issue
Block a user