Skip to content

Commit

Permalink
[networking] Add extensions attribute to Response (#9756)
Browse files Browse the repository at this point in the history
CurlCFFIRH now provides an `impersonate` field in its responses' extensions

Authored by: bashonly
  • Loading branch information
bashonly committed May 4, 2024
1 parent 036e0d9 commit bec9a59
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
19 changes: 19 additions & 0 deletions test/test_networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,25 @@ def test_supported_impersonate_targets(self, handler):
assert res.status == 200
assert std_headers['user-agent'].lower() not in res.read().decode().lower()

def test_response_extensions(self, handler):
with handler() as rh:
for target in rh.supported_targets:
request = Request(
f'http://127.0.0.1:{self.http_port}/gen_200', extensions={'impersonate': target})
res = validate_and_send(rh, request)
assert res.extensions['impersonate'] == rh._get_request_target(request)

def test_http_error_response_extensions(self, handler):
with handler() as rh:
for target in rh.supported_targets:
request = Request(
f'http://127.0.0.1:{self.http_port}/gen_404', extensions={'impersonate': target})
try:
validate_and_send(rh, request)
except HTTPError as e:
res = e.response
assert res.extensions['impersonate'] == rh._get_request_target(request)


class TestRequestHandlerMisc:
"""Misc generic tests for request handlers, not related to request or validation testing"""
Expand Down
10 changes: 10 additions & 0 deletions yt_dlp/networking/_curlcffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ def _check_extensions(self, extensions):
extensions.pop('cookiejar', None)
extensions.pop('timeout', None)

def send(self, request: Request) -> Response:
target = self._get_request_target(request)
try:
response = super().send(request)
except HTTPError as e:
e.response.extensions['impersonate'] = target
raise
response.extensions['impersonate'] = target
return response

def _send(self, request: Request):
max_redirects_exceeded = False
session: curl_cffi.requests.Session = self._get_instance(
Expand Down
6 changes: 5 additions & 1 deletion yt_dlp/networking/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ class Response(io.IOBase):
@param headers: response headers.
@param status: Response HTTP status code. Default is 200 OK.
@param reason: HTTP status reason. Will use built-in reasons based on status code if not provided.
@param extensions: Dictionary of handler-specific response extensions.
"""

def __init__(
Expand All @@ -505,7 +506,9 @@ def __init__(
url: str,
headers: Mapping[str, str],
status: int = 200,
reason: str = None):
reason: str = None,
extensions: dict = None
):

self.fp = fp
self.headers = Message()
Expand All @@ -517,6 +520,7 @@ def __init__(
self.reason = reason or HTTPStatus(status).phrase
except ValueError:
self.reason = None
self.extensions = extensions or {}

def readable(self):
return self.fp.readable()
Expand Down

0 comments on commit bec9a59

Please sign in to comment.