From da339193685c04f31d114df2bb977a62bf811123 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Sun, 24 May 2026 22:26:56 +0000 Subject: [PATCH] =?UTF-8?q?f1-stream:=20verifier=20=E2=80=94=20wrap=20m3u8?= =?UTF-8?q?=20fetches=20through=20/proxy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The frontend already routes every m3u8 URL through `getProxyUrl` → `/proxy?url=…` so CORS-restricted hosts work for users. The verifier was the odd one out: it loaded m3u8 URLs directly into hls.js inside a `data:` URL test page, which has Origin `null`. Hosts like `oe1.ossfeed.store` (pitsport's playlist CDN) only set ACAO when the request's Origin is `https://pushembdz.store`, so hls.js got an instant `fatal_network_error` and every pitsport stream was marked dead even though they play fine for real users. Wrap the m3u8 URL the same way the verifier already wraps embed URLs: `{PROXY_BASE}/proxy?url=`. Stays same-origin for hls.js, gets ACAO:* from our proxy, and the rewritten variants are also proxy-wrapped so subsequent fetches stay clean. For sites whose CDN serves any IP without Origin tricks (stremio, dd12), this is transparent — proxy just forwards. Side effect: every verified m3u8 hits our proxy once during extraction. Cheap (1 cluster-internal request + 1 upstream HEAD/GET) and only during the 5/30-min extraction cycle. --- stacks/f1-stream/files/backend/playback_verifier.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/stacks/f1-stream/files/backend/playback_verifier.py b/stacks/f1-stream/files/backend/playback_verifier.py index bb239f70..d6ff1d7f 100644 --- a/stacks/f1-stream/files/backend/playback_verifier.py +++ b/stacks/f1-stream/files/backend/playback_verifier.py @@ -381,7 +381,15 @@ class PlaybackVerifier: return PlaybackVerdict(is_playable=False, error="playwright unavailable") is_m3u8 = stream_type == "m3u8" - if not is_m3u8: + if is_m3u8: + # Route m3u8 fetches through our own /proxy so the verifier gets a + # same-origin response with ACAO:* — matches what the frontend does + # (frontend `getProxyUrl` wraps every m3u8 via /proxy anyway). Without + # this, hosts like oe1.ossfeed.store that only return CORS headers + # for specific Origins (e.g. pushembdz.store) trigger an immediate + # `fatal_network_error` in hls.js and the stream is marked dead. + url = f"{PROXY_BASE}/proxy?url={_b64url(url)}" + else: url = f"{PROXY_BASE}/embed?url={_b64url(url)}" async with self._sem: