fix: detectHttpByteRanges should still try a Range GET after an inconclusive HEAD - #1245
Open
gavrichards wants to merge 1 commit into
Open
Conversation
…clusive HEAD detectHttpByteRanges()'s docstring says it does 'HEAD, then Range probe', but the code only tried the Range GET when the HEAD request itself threw. Any HEAD response that merely succeeded without an Accept-Ranges: bytes header was treated as decisive proof of no range support, even though the intended fallback probe was never attempted. This misdetects real servers: confirmed against a live public Icecast stream (SomaFM) that returns 200 OK on HEAD with no Accept-Ranges header, but answers a Range GET with a genuine 206 Partial Content. Sending that case to detectHttpByteRanges's fallback (rather than returning false immediately) lets loadRemoteHttpSource correctly hand the URL to native code instead of attempting to buffer an indefinite live stream into memory via response.arrayBuffer(), which never resolves. Fix: only short-circuit to true when Accept-Ranges: bytes is confirmed; any other HEAD outcome (ok-but-inconclusive, non-ok, or thrown) now falls through to the Range GET probe, matching the function's own documented behavior. Verified against the real repro: before this change, loading https://ice1.somafm.com/groovesalad-128-mp3 through loadRemoteHttpSource() (FFmpeg enabled) never resolved; after, it resolves in <1s. The FFmpeg- disabled path (which skips byte-range detection by design) still hangs on the same URL — that's a separate, deeper gap tracked for a follow-up PR (an explicit stream/type hint on AudioURISource), not something this fix is meant to address. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WPT non-regression comparisonPASS — no regressions · 0 improved section(s) · overall 2632 → 2632 (0) Unchanged sections (28)
Baseline: Workflow run · this comment is updated on every push. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
detectHttpByteRanges()'s own docstring says it does "HEAD, then Range probe" — but the code only tried the Range GET fallback when the HEAD request itself threw. Any HEAD response that merely succeeded, even without anAccept-Ranges: bytesheader, was treated as decisive proof of "no range support," short-circuiting before the documented fallback probe ever ran.Why this matters
This misdetects real servers. Confirmed against a live public Icecast stream (SomaFM):
The server answers a Range GET with a genuine
206, but itsHEADresponse never mentions ranges at all — a common pattern for Icecast/Shoutcast configs. Under the current logic,detectHttpByteRangesgives up right after the HEAD check and never finds this out, soloadRemoteHttpSourcefalls back todownloadRemoteHttpSource(), which callsresponse.arrayBuffer()— and for a genuinely indefinite live stream, that promise never resolves.The fix
Only short-circuit to
truewhenAccept-Ranges: bytesis actually confirmed on the HEAD response. Any other outcome (HEAD ok-but-inconclusive, non-ok, or thrown) now falls through to the Range GET probe, matching the function's own documented behavior. Minimal diff, no behavior change for the cases that were already working correctly.Testing
typecheck/lint:js: clean.https://ice1.somafm.com/groovesalad-128-mp3throughloadRemoteHttpSource()(FFmpeg enabled) never resolved before this fix; it resolves in <1s after.What this doesn't fix
The FFmpeg-disabled path skips byte-range detection entirely by design (
if (!isFfmpegEnabled() || forceDownload) return downloadRemoteHttpSource(...)), so it still hangs on the same URL — that's unrelated to this bug and not something this PR claims to address. For servers that genuinely don't support ranges at all (not just omit the header), there's still no way for a caller to say "this is a live stream, don't try to buffer it" up front. I'd like to follow up with that as a separate PR (an explicit hint onAudioURISource) once this one's settled, rather than combine the two.