Repository navigation
Conversation
getFullURL built absolute URLs for relative URIs with appendingPathComponent. That method percent-encodes '?' into '%3F', so a variant URI such as 'video.m3u8?hdntl=...' became part of the path and the server returned HTTP 400. Resolve the URI against the manifest URL with URL(string:relativeTo:) instead. Fall back to the previous behavior when that fails.
Cover relative URIs with a query string in the same directory, in a subdirectory and in a parent directory, a relative URI without a query, and an absolute URI. A relative URI without its own query does not get the playlist's query, as RFC 3986 section 5.2.2 specifies.
Contributor
|
Hi @olejnjak, Thank you very much for your PR! This is indeed fixing a real problem with signed playlists URLs being broken, but it seems to introduce an edge case where While reviewing this PR, we also found 3 other edge cases where some encoding/decoding issues happen. Instead of merging this PR, we will work on a more robust solution that fixes all the cases we have found so that we fix the root cause and not a specific case. Would you please create a ticket on our Service Desk in the meantime with a source description that reproduced an issue on your end so that we can also use it to test the fix? |
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.
Problem
When a source has sideloaded subtitles, the connector rewrites the HLS playlists. If the master
playlist lists variant playlists as relative URIs with a query string, playback fails.
Example of a variant URI in the master playlist:
The connector requests it as:
The
?is percent-encoded, so the query becomes part of the path. The CDN returns HTTP 400 foreach variant playlist, and THEOplayer reports a network error (6400). The same stream plays
correctly without sideloaded subtitles.
Cause
PlaylistParser.getFullURL(from:)builds the absolute URL of a relative URI withmanifestURL.deletingLastPathComponent().appendingPathComponent(path).appendingPathComponenttreats its whole argument as a path component, so it percent-encodes?to
%3F.Fix
Resolve a relative URI against the manifest URL with
URL(string:relativeTo:). This keeps thequery string as a query and also handles
../and subdirectory paths. If that initializerreturns
nil, the code falls back to the previousappendingPathComponentbehavior. AbsoluteURIs are not affected.
A relative URI without its own query no longer gets the playlist's query string. The previous
code added it as a side effect of
appendingPathComponent. The new result follows RFC 3986section 5.2.2, which RFC 8216bis section 4.1 refers to for resolving relative URIs, and matches
AVPlayer's own resolution. A stream that needs the playlist's query on other URIs can use
EXT-X-DEFINEwithQUERYPARAM.Tests
Added
PlaylistParserTestswith these cases, resolved againsthttps://cdn.example.com/vod/movie/index.m3u8?token=abc:video=391132.m3u8?hdntl=……/movie/video=391132.m3u8?hdntl=…keyframes/video.m3u8?accountId=1…/movie/keyframes/video.m3u8?accountId=1../other/video.m3u8?accountId=1…/vod/other/video.m3u8?accountId=1video.m3u8…/movie/video.m3u8https://other.example.com/video.m3u8?token=xyz(absolute)All five pass with the fix. With the previous
getFullURL, the four relative cases fail.Also checked on an iOS device with an HLS VOD stream whose master playlist has relative variant
URIs with a signed
hdntlquery, plus sideloaded WebVTT subtitles. Before the fix every variantplaylist request returned HTTP 400 and playback failed. After the fix the variant playlists load
with their query string, and the stream plays.
Changelog
Added an entry under Unreleased → Fixed → SideloadedSubtitle.