mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-14 21:15:06 +00:00
fix(downloader): fail closed on rnet content codings outside the old allowlist
The rnet branch zeroed content_length only for gzip/deflate/br, so an unknown coding (zstd, future tokens) kept a bogus length and, worse, the drop-the-partial-instead-of-Range-resuming guard could never fire on the rnet path because content_encoded stayed False. Use the same fail-closed _is_content_encoded check the requests branch uses.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import gzip
|
||||
import importlib
|
||||
import socket
|
||||
import threading
|
||||
|
||||
@@ -108,3 +109,48 @@ def test_encoded_body_discards_a_partial_instead_of_range_resuming(tmp_path, enc
|
||||
save_path.with_name("sub.vtt.!dev").write_bytes(PLAIN[:5000])
|
||||
list(download(url=encoding_server.url, save_path=save_path, session=rq.Session()))
|
||||
assert save_path.read_bytes() == PLAIN
|
||||
|
||||
|
||||
class _FakeRnetResponse:
|
||||
def __init__(self, status_code, headers, body):
|
||||
self.status_code = status_code
|
||||
self.headers = headers
|
||||
self.content_length = len(body)
|
||||
self._body = body
|
||||
|
||||
def raise_for_status(self):
|
||||
pass
|
||||
|
||||
def stream(self):
|
||||
yield self._body
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
||||
class _FakeRnetSession:
|
||||
"""Duck-typed rnet stand-in: an encoded 206 for a Range request (the resume the
|
||||
fail-closed guard must reject), an encoded 200 for the clean restart."""
|
||||
|
||||
def __init__(self, body):
|
||||
self.body = body
|
||||
self.range_requests = 0
|
||||
|
||||
def get(self, url, stream=True, **kwargs):
|
||||
headers = kwargs.get("headers") or {}
|
||||
if any(k.lower() == "range" for k in headers):
|
||||
self.range_requests += 1
|
||||
return _FakeRnetResponse(206, {"Content-Encoding": "zstd"}, b"\x00mid-stream-slice\x00")
|
||||
return _FakeRnetResponse(200, {"Content-Encoding": "zstd"}, self.body)
|
||||
|
||||
|
||||
def test_rnet_encoded_body_discards_a_partial_instead_of_range_resuming(tmp_path, monkeypatch):
|
||||
dl = importlib.import_module("unshackle.core.downloaders.requests")
|
||||
monkeypatch.setattr(dl, "_is_rnet_session", lambda s: isinstance(s, _FakeRnetSession))
|
||||
session = _FakeRnetSession(PLAIN)
|
||||
save_path = tmp_path / "sub.vtt"
|
||||
save_path.with_name("sub.vtt.!dev").write_bytes(PLAIN[:5000])
|
||||
list(download(url="http://127.0.0.1:1/sub.vtt", save_path=save_path, session=session))
|
||||
# the encoded 206 must be dropped (never appended); the restart fetches the whole body
|
||||
assert session.range_requests == 1
|
||||
assert save_path.read_bytes() == PLAIN
|
||||
|
||||
Reference in New Issue
Block a user