diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e2685a..428507fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- SideloadedSubtitle + - Fixed an issue where internal network requests would cause a user agent mismatch. + ## [11.0.1] - 2026-04-21 ### Fixed diff --git a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift index a552d0d5..6ae35533 100644 --- a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift +++ b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift @@ -22,6 +22,7 @@ class AVSubtitlesLoader: NSObject { private let synchronizer: SubtitlesSynchronizer? private let _id: String private var variantTotalDuration: Double = 0 + private var requestMap: [URL: URLRequest] = [:] init(subtitles: [TextTrackDescription], id: String, player: THEOplayer? = nil) { self._subtitles = subtitles @@ -42,8 +43,8 @@ class AVSubtitlesLoader: NSObject { } #endif - func handleMasterManifestRequest(_ url: URL) async -> Data? { - let parser = MasterPlaylistParser(url: url) + func handleMasterManifestRequest(_ url: URL, request: URLRequest?) async -> Data? { + let parser = MasterPlaylistParser(url: url, request: request) guard let responseData = await parser.sideLoadSubtitles(subtitles: subtitles) else { print("[AVSubtitlesLoader] ERROR: Couldn't find manifest data") return nil @@ -52,8 +53,8 @@ class AVSubtitlesLoader: NSObject { return responseData } - func handleVariantManifest(_ url: URL) async -> Data? { - let parser = VariantPlaylistParser(url: url) + func handleVariantManifest(_ url: URL, request: URLRequest?) async -> Data? { + let parser = VariantPlaylistParser(url: url, request: request) guard let playlist = await parser.parse(), let responseData = playlist.manifestData else { @@ -163,8 +164,13 @@ enum URLScheme: String { } extension AVSubtitlesLoader: MediaPlaylistInterceptor { - func shouldInterceptPlaylistRequest(type: HlsPlaylistType) -> Bool { false } - func didInterceptPlaylistRequest(type: HlsPlaylistType, request: URLRequest) async throws -> URLRequest { request } + func shouldInterceptPlaylistRequest(type: HlsPlaylistType) -> Bool { true } + func didInterceptPlaylistRequest(type: HlsPlaylistType, request: URLRequest) async throws -> URLRequest { + if let url = request.url { + requestMap[url] = request + } + return request + } func failedToPerformURLRequest(request: URLRequest, response: URLResponse) { if THEOplayerConnectorSideloadedSubtitle.SHOW_DEBUG_LOGS { @@ -190,11 +196,11 @@ extension AVSubtitlesLoader: MediaPlaylistInterceptor { // intercept the master manifest to append the subtitles subtitles = await validateSubtitles() if subtitles.isEmpty { return data } - return await self.handleMasterManifestRequest(url) ?? data + return await self.handleMasterManifestRequest(url, request: requestMap[url]) ?? data case .video: // intercept the variant manifest to get the duration if subtitles.isEmpty { return data } - return await self.handleVariantManifest(url) ?? data + return await self.handleVariantManifest(url, request: requestMap[url]) ?? data case .subtitles: // intercept the subtitle request to respond with the HLS subtitle if subtitles.isEmpty { return data } diff --git a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/MasterPlaylistParser.swift b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/MasterPlaylistParser.swift index 292fcdb5..83416ab3 100644 --- a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/MasterPlaylistParser.swift +++ b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/MasterPlaylistParser.swift @@ -12,13 +12,10 @@ class MasterPlaylistParser: PlaylistParser { var constructedManifestArray = [String]() fileprivate var lastMediaLine: Int? fileprivate let subtitlesGroupId = "THEOsubs" - - override init(url: URL) { - super.init(url: url) - } func sideLoadSubtitles(subtitles: [TextTrackDescription]) async -> Data? { - guard let _ = await self.loadManifest() else { return nil } + let headers = request?.allHTTPHeaderFields + guard let _ = await self.loadManifest(headers) else { return nil } self.parseManifest() self.appendSubtitlesLines(subtitles: subtitles) let constructed = self.constructedManifestArray.joined(separator: "\n") diff --git a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/PlaylistParser.swift b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/PlaylistParser.swift index d50dbf81..aad3cf55 100644 --- a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/PlaylistParser.swift +++ b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/PlaylistParser.swift @@ -10,14 +10,22 @@ import Foundation class PlaylistParser { var manifestURL: URL var manifestData: Data? + let request: URLRequest? - init(url: URL) { + init(url: URL, request: URLRequest?) { self.manifestURL = url self.manifestData = nil + self.request = request } - func loadManifest() async -> Data? { - if let (data, response) = try? await URLSession.shared.data(from: self.manifestURL) { + func loadManifest(_ headers: [String: String]? = nil) async -> Data? { + var request = URLRequest(url: self.manifestURL) + if let headers { + for header in headers { + request.setValue(header.value, forHTTPHeaderField: header.key) + } + } + if let (data, response) = try? await URLSession.shared.data(for: request) { // Update the manifestUrl to the url received in the response (to pickup possible url redirect) if let responseUrl = response.url { self.manifestURL = responseUrl diff --git a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/VariantPlaylistParser.swift b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/VariantPlaylistParser.swift index 72adf59d..35c533c9 100644 --- a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/VariantPlaylistParser.swift +++ b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/Parsers/VariantPlaylistParser.swift @@ -11,13 +11,14 @@ class VariantPlaylistParser: PlaylistParser { fileprivate(set) var totalPlayListDuration: Double var constructedManifestArray = [String]() - override init(url: URL) { + override init(url: URL, request: URLRequest?) { self.totalPlayListDuration = 0 - super.init(url: url) + super.init(url: url, request: request) } func parse() async -> VariantPlaylistParser? { - guard let _ = await self.loadManifest() else { return nil } + let headers = request?.allHTTPHeaderFields + guard let _ = await self.loadManifest(headers) else { return nil } self.parseManifest() let constructed = self.constructedManifestArray.joined(separator: "\n") if THEOplayerConnectorSideloadedSubtitle.SHOW_DEBUG_LOGS {