mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-09 06:27:06 +01:00
Handle urllib3 not being available
This commit is contained in:
parent
3999a510f7
commit
01fe8e8fa6
@ -156,7 +156,10 @@ def __init__(self, request, *args, **kwargs):
|
|||||||
certfn = os.path.join(TEST_DIR, 'testcert.pem')
|
certfn = os.path.join(TEST_DIR, 'testcert.pem')
|
||||||
sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
sslctx.load_cert_chain(certfn, None)
|
sslctx.load_cert_chain(certfn, None)
|
||||||
request = SSLTransport(request, ssl_context=sslctx, server_side=True)
|
if SSLTransport:
|
||||||
|
request = SSLTransport(request, ssl_context=sslctx, server_side=True)
|
||||||
|
else:
|
||||||
|
request = sslctx.wrap_socket(request, server_side=True)
|
||||||
super().__init__(request, *args, **kwargs)
|
super().__init__(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -4137,15 +4137,15 @@ def urlopen(self, req):
|
|||||||
'Use --enable-file-urls to enable at your own risk.', cause=ue) from ue
|
'Use --enable-file-urls to enable at your own risk.', cause=ue) from ue
|
||||||
if (
|
if (
|
||||||
'unsupported proxy type: "https"' in ue.msg.lower()
|
'unsupported proxy type: "https"' in ue.msg.lower()
|
||||||
and 'requests' not in self._request_director.handlers
|
and 'Requests' not in self._request_director.handlers
|
||||||
and 'curl_cffi' not in self._request_director.handlers
|
and 'CurlCFFI' not in self._request_director.handlers
|
||||||
):
|
):
|
||||||
raise RequestError(
|
raise RequestError(
|
||||||
'To use an HTTPS proxy for this request, one of the following dependencies needs to be installed: requests, curl_cffi')
|
'To use an HTTPS proxy for this request, one of the following dependencies needs to be installed: requests, curl_cffi')
|
||||||
|
|
||||||
elif (
|
elif (
|
||||||
re.match(r'unsupported url scheme: "wss?"', ue.msg.lower())
|
re.match(r'unsupported url scheme: "wss?"', ue.msg.lower())
|
||||||
and 'websockets' not in self._request_director.handlers
|
and 'Websockets' not in self._request_director.handlers
|
||||||
):
|
):
|
||||||
raise RequestError(
|
raise RequestError(
|
||||||
'This request requires WebSocket support. '
|
'This request requires WebSocket support. '
|
||||||
|
@ -19,20 +19,18 @@
|
|||||||
ProxyError,
|
ProxyError,
|
||||||
RequestError,
|
RequestError,
|
||||||
SSLError,
|
SSLError,
|
||||||
TransportError,
|
TransportError, UnsupportedRequest,
|
||||||
)
|
)
|
||||||
from .websocket import WebSocketRequestHandler, WebSocketResponse
|
from .websocket import WebSocketRequestHandler, WebSocketResponse
|
||||||
from ..compat import functools
|
from ..compat import functools
|
||||||
from ..dependencies import websockets
|
from ..dependencies import websockets, urllib3
|
||||||
from ..socks import ProxyError as SocksProxyError
|
from ..socks import ProxyError as SocksProxyError
|
||||||
from ..utils import int_or_none, extract_basic_auth
|
from ..utils import int_or_none
|
||||||
import io
|
import io
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
from http.client import HTTPResponse, HTTPConnection, HTTPSConnection
|
from http.client import HTTPResponse, HTTPConnection
|
||||||
|
|
||||||
from urllib3.util.ssltransport import SSLTransport
|
|
||||||
|
|
||||||
from ..utils.networking import HTTPHeaderDict
|
from ..utils.networking import HTTPHeaderDict
|
||||||
|
|
||||||
@ -45,6 +43,11 @@
|
|||||||
if websockets_version < (12, 0):
|
if websockets_version < (12, 0):
|
||||||
raise ImportError('Only websockets>=12.0 is supported')
|
raise ImportError('Only websockets>=12.0 is supported')
|
||||||
|
|
||||||
|
urllib3_supported = False
|
||||||
|
urllib3_version = tuple(int_or_none(x, default=0) for x in urllib3.__version__.split('.')) if urllib3 else None
|
||||||
|
if urllib3_version and urllib3_version >= (1, 26, 17):
|
||||||
|
urllib3_supported = True
|
||||||
|
|
||||||
import websockets.sync.client
|
import websockets.sync.client
|
||||||
from websockets.uri import parse_uri
|
from websockets.uri import parse_uri
|
||||||
|
|
||||||
@ -124,6 +127,17 @@ def __init__(self, *args, **kwargs):
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
def _validate(self, request):
|
||||||
|
super()._validate(request)
|
||||||
|
proxy = select_proxy(request.url, self._get_proxies(request))
|
||||||
|
if (
|
||||||
|
proxy
|
||||||
|
and urllib.parse.urlparse(proxy).scheme.lower() == 'https'
|
||||||
|
and urllib.parse.urlparse(request.url).scheme.lower() == 'wss'
|
||||||
|
and not urllib3_supported
|
||||||
|
):
|
||||||
|
raise UnsupportedRequest('WSS over HTTPS proxies requires a supported version of urllib3')
|
||||||
|
|
||||||
def _check_extensions(self, extensions):
|
def _check_extensions(self, extensions):
|
||||||
super()._check_extensions(extensions)
|
super()._check_extensions(extensions)
|
||||||
extensions.pop('timeout', None)
|
extensions.pop('timeout', None)
|
||||||
@ -178,6 +192,12 @@ def _send(self, request):
|
|||||||
|
|
||||||
proxy = select_proxy(request.url, self._get_proxies(request))
|
proxy = select_proxy(request.url, self._get_proxies(request))
|
||||||
|
|
||||||
|
ssl_context = None
|
||||||
|
if parse_uri(request.url).secure:
|
||||||
|
if WebsocketsSSLContext is not None:
|
||||||
|
ssl_context = WebsocketsSSLContext(self._make_sslcontext())
|
||||||
|
else:
|
||||||
|
ssl_context = self._make_sslcontext()
|
||||||
try:
|
try:
|
||||||
conn = websockets.sync.client.connect(
|
conn = websockets.sync.client.connect(
|
||||||
sock=self._make_sock(proxy, request.url, timeout),
|
sock=self._make_sock(proxy, request.url, timeout),
|
||||||
@ -185,10 +205,7 @@ def _send(self, request):
|
|||||||
additional_headers=headers,
|
additional_headers=headers,
|
||||||
open_timeout=timeout,
|
open_timeout=timeout,
|
||||||
user_agent_header=None,
|
user_agent_header=None,
|
||||||
ssl_context=(
|
ssl_context=ssl_context,
|
||||||
WebsocketsSSLContext(self._make_sslcontext())
|
|
||||||
if parse_uri(request.url).secure else None
|
|
||||||
),
|
|
||||||
close_timeout=0, # not ideal, but prevents yt-dlp hanging
|
close_timeout=0, # not ideal, but prevents yt-dlp hanging
|
||||||
)
|
)
|
||||||
return WebsocketsResponseAdapter(conn, url=request.url)
|
return WebsocketsResponseAdapter(conn, url=request.url)
|
||||||
@ -223,17 +240,21 @@ def begin(self):
|
|||||||
self.will_close = False
|
self.will_close = False
|
||||||
|
|
||||||
|
|
||||||
# todo: only define if urllib3 is available
|
if urllib3_supported:
|
||||||
class WebsocketsSSLTransport(SSLTransport):
|
from urllib3.util.ssltransport import SSLTransport
|
||||||
"""
|
|
||||||
Modified version of urllib3 SSLTransport to support additional operations used by websockets
|
|
||||||
"""
|
|
||||||
def setsockopt(self, *args, **kwargs):
|
|
||||||
self.socket.setsockopt(*args, **kwargs)
|
|
||||||
|
|
||||||
def shutdown(self, *args, **kwargs):
|
class WebsocketsSSLTransport(SSLTransport):
|
||||||
self.unwrap()
|
"""
|
||||||
self.socket.shutdown(*args, **kwargs)
|
Modified version of urllib3 SSLTransport to support additional operations used by websockets
|
||||||
|
"""
|
||||||
|
def setsockopt(self, *args, **kwargs):
|
||||||
|
self.socket.setsockopt(*args, **kwargs)
|
||||||
|
|
||||||
|
def shutdown(self, *args, **kwargs):
|
||||||
|
self.unwrap()
|
||||||
|
self.socket.shutdown(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
WebsocketsSSLTransport = None
|
||||||
|
|
||||||
|
|
||||||
class WebsocketsSSLContext:
|
class WebsocketsSSLContext:
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from .common import RequestHandler, Response
|
from .common import RequestHandler, Response, register_preference
|
||||||
|
|
||||||
|
|
||||||
class WebSocketResponse(Response):
|
class WebSocketResponse(Response):
|
||||||
@ -21,3 +22,10 @@ def recv(self):
|
|||||||
|
|
||||||
class WebSocketRequestHandler(RequestHandler, abc.ABC):
|
class WebSocketRequestHandler(RequestHandler, abc.ABC):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@register_preference(WebSocketRequestHandler)
|
||||||
|
def websocket_preference(_, request):
|
||||||
|
if urllib.parse.urlparse(request.url).scheme in ('ws', 'wss'):
|
||||||
|
return 200
|
||||||
|
return 0
|
||||||
|
Loading…
Reference in New Issue
Block a user