kopia lustrzana https://github.com/yt-dlp/yt-dlp
rodzic
8056a3026e
commit
64d4c4ba72
|
@ -5,13 +5,7 @@ import math
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from ._helper import InstanceStoreMixin, select_proxy
|
from ._helper import InstanceStoreMixin, select_proxy
|
||||||
from .common import (
|
from .common import Features, Request, register_preference, register_rh
|
||||||
Features,
|
|
||||||
Request,
|
|
||||||
Response,
|
|
||||||
register_preference,
|
|
||||||
register_rh,
|
|
||||||
)
|
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
CertificateVerifyError,
|
CertificateVerifyError,
|
||||||
HTTPError,
|
HTTPError,
|
||||||
|
@ -20,7 +14,11 @@ from .exceptions import (
|
||||||
SSLError,
|
SSLError,
|
||||||
TransportError,
|
TransportError,
|
||||||
)
|
)
|
||||||
from .impersonate import ImpersonateRequestHandler, ImpersonateTarget
|
from .impersonate import (
|
||||||
|
ImpersonateRequestHandler,
|
||||||
|
ImpersonateResponse,
|
||||||
|
ImpersonateTarget,
|
||||||
|
)
|
||||||
from ..dependencies import curl_cffi
|
from ..dependencies import curl_cffi
|
||||||
from ..utils import int_or_none
|
from ..utils import int_or_none
|
||||||
|
|
||||||
|
@ -80,15 +78,16 @@ class CurlCFFIResponseReader(io.IOBase):
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
|
|
||||||
class CurlCFFIResponseAdapter(Response):
|
class CurlCFFIResponseAdapter(ImpersonateResponse):
|
||||||
fp: CurlCFFIResponseReader
|
fp: CurlCFFIResponseReader
|
||||||
|
|
||||||
def __init__(self, response: curl_cffi.requests.Response):
|
def __init__(self, response: curl_cffi.requests.Response, impersonate: ImpersonateTarget):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
fp=CurlCFFIResponseReader(response),
|
fp=CurlCFFIResponseReader(response),
|
||||||
headers=response.headers,
|
headers=response.headers,
|
||||||
url=response.url,
|
url=response.url,
|
||||||
status=response.status_code)
|
status=response.status_code,
|
||||||
|
impersonate=impersonate)
|
||||||
|
|
||||||
def read(self, amt=None):
|
def read(self, amt=None):
|
||||||
try:
|
try:
|
||||||
|
@ -178,6 +177,8 @@ class CurlCFFIRH(ImpersonateRequestHandler, InstanceStoreMixin):
|
||||||
session.curl.setopt(CurlOpt.LOW_SPEED_LIMIT, 1) # 1 byte per second
|
session.curl.setopt(CurlOpt.LOW_SPEED_LIMIT, 1) # 1 byte per second
|
||||||
session.curl.setopt(CurlOpt.LOW_SPEED_TIME, math.ceil(timeout))
|
session.curl.setopt(CurlOpt.LOW_SPEED_TIME, math.ceil(timeout))
|
||||||
|
|
||||||
|
impersonate_target = self._get_request_target(request)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
curl_response = session.request(
|
curl_response = session.request(
|
||||||
method=request.method,
|
method=request.method,
|
||||||
|
@ -187,8 +188,7 @@ class CurlCFFIRH(ImpersonateRequestHandler, InstanceStoreMixin):
|
||||||
verify=self.verify,
|
verify=self.verify,
|
||||||
max_redirects=5,
|
max_redirects=5,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
impersonate=self._SUPPORTED_IMPERSONATE_TARGET_MAP.get(
|
impersonate=self._SUPPORTED_IMPERSONATE_TARGET_MAP.get(impersonate_target),
|
||||||
self._get_request_target(request)),
|
|
||||||
interface=self.source_address,
|
interface=self.source_address,
|
||||||
stream=True
|
stream=True
|
||||||
)
|
)
|
||||||
|
@ -208,7 +208,7 @@ class CurlCFFIRH(ImpersonateRequestHandler, InstanceStoreMixin):
|
||||||
else:
|
else:
|
||||||
raise TransportError(cause=e) from e
|
raise TransportError(cause=e) from e
|
||||||
|
|
||||||
response = CurlCFFIResponseAdapter(curl_response)
|
response = CurlCFFIResponseAdapter(curl_response, impersonate_target)
|
||||||
|
|
||||||
if not 200 <= response.status < 300:
|
if not 200 <= response.status < 300:
|
||||||
raise HTTPError(response, redirect_loop=max_redirects_exceeded)
|
raise HTTPError(response, redirect_loop=max_redirects_exceeded)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from abc import ABC
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from .common import RequestHandler, register_preference
|
from .common import RequestHandler, Response, register_preference
|
||||||
from .exceptions import UnsupportedRequest
|
from .exceptions import UnsupportedRequest
|
||||||
from ..compat.types import NoneType
|
from ..compat.types import NoneType
|
||||||
from ..utils import classproperty, join_nonempty
|
from ..utils import classproperty, join_nonempty
|
||||||
|
@ -58,6 +58,18 @@ class ImpersonateTarget:
|
||||||
return cls(**mobj.groupdict())
|
return cls(**mobj.groupdict())
|
||||||
|
|
||||||
|
|
||||||
|
class ImpersonateResponse(Response):
|
||||||
|
"""
|
||||||
|
Wrapper class for a Response to an impersonated Request.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
@param impersonate: the ImpersonateTarget used in the originating Request.
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, impersonate: ImpersonateTarget, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.impersonate = impersonate
|
||||||
|
|
||||||
|
|
||||||
class ImpersonateRequestHandler(RequestHandler, ABC):
|
class ImpersonateRequestHandler(RequestHandler, ABC):
|
||||||
"""
|
"""
|
||||||
Base class for request handlers that support browser impersonation.
|
Base class for request handlers that support browser impersonation.
|
||||||
|
|
Ładowanie…
Reference in New Issue