mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-08-17 01:26:16 +03:00
[rh:curl_cffi] Support curl_cffi 0.16.x (#17439)
Closes #17341 Authored by: bashonly, coletdjnz Co-authored-by: coletdjnz <coletdjnz@protonmail.com>
This commit is contained in:
@@ -97,7 +97,6 @@ BUNDLE_TARGETS = {
|
|||||||
extras=['curl-cffi'],
|
extras=['curl-cffi'],
|
||||||
# Only need curl-cffi+cffi in this requirements file; their deps are installed directly
|
# Only need curl-cffi+cffi in this requirements file; their deps are installed directly
|
||||||
# XXX: Try to keep these in sync with curl-cffi's and cffi's transitive dependencies
|
# XXX: Try to keep these in sync with curl-cffi's and cffi's transitive dependencies
|
||||||
prune_packages=['rich'],
|
|
||||||
omit_packages=['certifi', 'pycparser'],
|
omit_packages=['certifi', 'pycparser'],
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -58,7 +58,7 @@ default = [
|
|||||||
"yt-dlp-ejs==0.8.0",
|
"yt-dlp-ejs==0.8.0",
|
||||||
]
|
]
|
||||||
curl-cffi = [
|
curl-cffi = [
|
||||||
"curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.16 ; implementation_name == 'cpython'",
|
"curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.17 ; implementation_name == 'cpython'",
|
||||||
]
|
]
|
||||||
secretstorage = [
|
secretstorage = [
|
||||||
"secretstorage",
|
"secretstorage",
|
||||||
|
|||||||
+22
-2
@@ -83,6 +83,12 @@ class HTTPProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
|
|||||||
|
|
||||||
self.server.close_request(self.request)
|
self.server.close_request(self.request)
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
try:
|
||||||
|
super().finish()
|
||||||
|
finally:
|
||||||
|
self.server.close_request(self.request)
|
||||||
|
|
||||||
|
|
||||||
if urllib3:
|
if urllib3:
|
||||||
import urllib3.util.ssltransport
|
import urllib3.util.ssltransport
|
||||||
@@ -132,7 +138,11 @@ class HTTPSProxyHandler(HTTPProxyHandler):
|
|||||||
request = SSLTransport(request, ssl_context=sslctx, server_side=True)
|
request = SSLTransport(request, ssl_context=sslctx, server_side=True)
|
||||||
else:
|
else:
|
||||||
request = sslctx.wrap_socket(request, server_side=True)
|
request = sslctx.wrap_socket(request, server_side=True)
|
||||||
super().__init__(request, *args, **kwargs)
|
try:
|
||||||
|
super().__init__(request, *args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
request.close()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
class HTTPConnectProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
|
class HTTPConnectProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
|
||||||
@@ -163,6 +173,12 @@ class HTTPConnectProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
|
|||||||
self.request_handler(self.request, self.client_address, self.server, proxy_info=proxy_info)
|
self.request_handler(self.request, self.client_address, self.server, proxy_info=proxy_info)
|
||||||
self.server.close_request(self.request)
|
self.server.close_request(self.request)
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
try:
|
||||||
|
super().finish()
|
||||||
|
finally:
|
||||||
|
self.server.close_request(self.request)
|
||||||
|
|
||||||
|
|
||||||
class HTTPSConnectProxyHandler(HTTPConnectProxyHandler):
|
class HTTPSConnectProxyHandler(HTTPConnectProxyHandler):
|
||||||
def __init__(self, request, *args, **kwargs):
|
def __init__(self, request, *args, **kwargs):
|
||||||
@@ -171,7 +187,11 @@ class HTTPSConnectProxyHandler(HTTPConnectProxyHandler):
|
|||||||
sslctx.load_cert_chain(certfn, None)
|
sslctx.load_cert_chain(certfn, None)
|
||||||
request = sslctx.wrap_socket(request, server_side=True)
|
request = sslctx.wrap_socket(request, server_side=True)
|
||||||
self._original_request = request
|
self._original_request = request
|
||||||
super().__init__(request, *args, **kwargs)
|
try:
|
||||||
|
super().__init__(request, *args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
request.close()
|
||||||
|
raise
|
||||||
|
|
||||||
def do_CONNECT(self):
|
def do_CONNECT(self):
|
||||||
super().do_CONNECT()
|
super().do_CONNECT()
|
||||||
|
|||||||
+12
-2
@@ -388,13 +388,23 @@ class TestHTTPRequestHandler(TestRequestHandlerBase):
|
|||||||
assert res.status == 200
|
assert res.status == 200
|
||||||
res.close()
|
res.close()
|
||||||
|
|
||||||
def test_percent_encode(self, handler):
|
def test_percent_encode_unicode(self, handler):
|
||||||
|
# RFC 3986 §6.2.2.1 defines that percent-encoding SHOULD be normalized to uppercase.
|
||||||
with handler() as rh:
|
with handler() as rh:
|
||||||
# Unicode characters should be encoded with uppercase percent-encoding
|
# Unicode characters should be encoded with uppercase percent-encoding
|
||||||
res = validate_and_send(rh, Request(f'http://127.0.0.1:{self.http_port}/中文.html'))
|
res = validate_and_send(rh, Request(f'http://127.0.0.1:{self.http_port}/中文.html'))
|
||||||
assert res.status == 200
|
assert res.status == 200
|
||||||
res.close()
|
res.close()
|
||||||
# don't normalize existing percent encodings
|
|
||||||
|
@pytest.mark.skip_handler('CurlCFFI', 'not supported by curl-cffi (non-standard)')
|
||||||
|
def test_percent_encode_keep_existing(self, handler):
|
||||||
|
# NOTE: RFC 3986 §6.2.2.1 defines that percent-encoding SHOULD be normalized to uppercase.
|
||||||
|
# For compatibility with legacy sites (e.g., redirects using lowercase encodings and only accept that),
|
||||||
|
# our default handlers (urllib/requests) preserve existing percent-encoding instead of normalizing it.
|
||||||
|
#
|
||||||
|
# CurlCFFI is excluded because it forces uppercase encodings and is hard to change. This is acceptable
|
||||||
|
# since CurlCFFI is used only for impersonation. https://github.com/curl/curl/pull/21592
|
||||||
|
with handler() as rh:
|
||||||
res = validate_and_send(rh, Request(f'http://127.0.0.1:{self.http_port}/%c7%9f'))
|
res = validate_and_send(rh, Request(f'http://127.0.0.1:{self.http_port}/%c7%9f'))
|
||||||
assert res.status == 200
|
assert res.status == 200
|
||||||
res.close()
|
res.close()
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ if curl_cffi is None:
|
|||||||
|
|
||||||
curl_cffi_version = tuple(map(int, re.split(r'[^\d]+', curl_cffi.__version__)[:3]))
|
curl_cffi_version = tuple(map(int, re.split(r'[^\d]+', curl_cffi.__version__)[:3]))
|
||||||
|
|
||||||
if curl_cffi_version != (0, 5, 10) and not (0, 10) <= curl_cffi_version < (0, 16):
|
if curl_cffi_version != (0, 5, 10) and not (0, 10) <= curl_cffi_version < (0, 17):
|
||||||
curl_cffi._yt_dlp__version = f'{curl_cffi.__version__} (unsupported)'
|
curl_cffi._yt_dlp__version = f'{curl_cffi.__version__} (unsupported)'
|
||||||
raise ImportError('Only curl_cffi versions 0.5.10 and 0.10.x through 0.15.x are supported')
|
raise ImportError('Only curl_cffi versions 0.5.10 and 0.10.x through 0.16.x are supported')
|
||||||
|
|
||||||
import curl_cffi.requests
|
import curl_cffi.requests
|
||||||
from curl_cffi.const import CurlECode, CurlOpt
|
from curl_cffi.const import CurlECode, CurlOpt
|
||||||
@@ -175,6 +175,9 @@ BROWSER_TARGETS: dict[tuple[int, ...], dict[str, ImpersonateTarget]] = {
|
|||||||
'firefox144': ImpersonateTarget('firefox', '144', 'macos', '26'),
|
'firefox144': ImpersonateTarget('firefox', '144', 'macos', '26'),
|
||||||
'firefox147': ImpersonateTarget('firefox', '147', 'macos', '26'),
|
'firefox147': ImpersonateTarget('firefox', '147', 'macos', '26'),
|
||||||
},
|
},
|
||||||
|
(0, 16, 1): {
|
||||||
|
'chrome150': ImpersonateTarget('chrome', '150', 'macos', '26'),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Needed for curl_cffi < 0.11
|
# Needed for curl_cffi < 0.11
|
||||||
@@ -327,7 +330,8 @@ class CurlCFFIRH(ImpersonateRequestHandler, InstanceStoreMixin):
|
|||||||
|
|
||||||
elif (
|
elif (
|
||||||
e.code == CurlECode.PROXY
|
e.code == CurlECode.PROXY
|
||||||
or (e.code == CurlECode.RECV_ERROR and 'CONNECT' in str(e))
|
# curl_cffi >= 0.16.0: changed to CurlECode.COULDNT_CONNECT https://github.com/curl/curl/pull/21084
|
||||||
|
or (e.code in (CurlECode.RECV_ERROR, CurlECode.COULDNT_CONNECT) and 'CONNECT' in str(e))
|
||||||
):
|
):
|
||||||
raise ProxyError(cause=e) from e
|
raise ProxyError(cause=e) from e
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user