wasm: openUrl takes Headers, aborts sibling requests on failure, checks parallel

- opts.headers is read as fetch reads it (a Headers, [name, value] pairs
  or a plain object); it was spread as an object, which silently dropped
  a Headers instance (a common way to pass Authorization). A caller's
  Range is not sent.
- When one range request of a batch fails, the others in flight are
  aborted (one AbortController per batch, its signal passed to fetch)
  and no new ones start; the first failure is the error. The workers
  used to go on issuing requests nobody waited for.
- parallel must be an integer from 1 to 1024 (openUrl) or a positive
  integer (fetchRanges): a non-number gave NaN workers, so none ran and
  fetchRanges returned nothing.

Tests (test.mjs): headers as object, Headers and pairs reach the fetch;
bad parallel values are option errors; fetchRanges with a 500 on the
third of 20 ranges at parallel 3 starts 3 requests and aborts the 2 in
flight. Before: the Headers case sent no header, 17 requests started
after the failure with none aborted, and parallel "x" returned.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-27 07:53:22 -05:00
co-authored by Claude Opus 5.5
parent 581c6ddef8
commit 2379e6163e
3 changed files with 127 additions and 44 deletions
+6 -2
View File
@@ -461,6 +461,8 @@ fn config_from(opts: &JsValue) -> Result<LazyConfig, JsError> {
// Read by remote.js; checked here so a value wasm32 cannot hold is an
// option error rather than a download that cannot be kept.
int_opt(opts, "maxDownload", 0.0, MAX_FETCH_LIMIT as f64)?;
// Also read by remote.js (which checks it too, for direct callers).
int_opt(opts, "parallel", 1.0, 1024.0)?;
Ok(c)
}
@@ -477,8 +479,10 @@ fn config_from(opts: &JsValue) -> Result<LazyConfig, JsError> {
/// - `fallback` — `"download"` (default) reads the whole file when the
/// server ignores `Range` (answers 200), up to `maxDownload` bytes
/// (default 512 MiB, at most 1 GiB); `"error"` refuses such a server;
/// - `headers`, `credentials` — passed to every `fetch`;
/// - `parallel` — range requests in flight at once (default 6);
/// - `headers`, `credentials` — passed to every `fetch` (`headers` as
/// `fetch` takes them: a `Headers`, `[name, value]` pairs or an object);
/// - `parallel` — range requests in flight at once, 1 to 1024 (default
/// 6); when one fails the others are aborted;
/// - `fetch` — a `fetch`-compatible function to use instead of the global.
///
/// Cross-origin servers must allow CORS and expose `Content-Range` (or