You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			256 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			256 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
from __future__ import annotations
 | 
						|
 | 
						|
import os
 | 
						|
import typing
 | 
						|
 | 
						|
# use http.client.HTTPException for consistency with non-emscripten
 | 
						|
from http.client import HTTPException as HTTPException  # noqa: F401
 | 
						|
from http.client import ResponseNotReady
 | 
						|
 | 
						|
from ..._base_connection import _TYPE_BODY
 | 
						|
from ...connection import HTTPConnection, ProxyConfig, port_by_scheme
 | 
						|
from ...exceptions import TimeoutError
 | 
						|
from ...response import BaseHTTPResponse
 | 
						|
from ...util.connection import _TYPE_SOCKET_OPTIONS
 | 
						|
from ...util.timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT
 | 
						|
from ...util.url import Url
 | 
						|
from .fetch import _RequestError, _TimeoutError, send_request, send_streaming_request
 | 
						|
from .request import EmscriptenRequest
 | 
						|
from .response import EmscriptenHttpResponseWrapper, EmscriptenResponse
 | 
						|
 | 
						|
if typing.TYPE_CHECKING:
 | 
						|
    from ..._base_connection import BaseHTTPConnection, BaseHTTPSConnection
 | 
						|
 | 
						|
 | 
						|
class EmscriptenHTTPConnection:
 | 
						|
    default_port: typing.ClassVar[int] = port_by_scheme["http"]
 | 
						|
    default_socket_options: typing.ClassVar[_TYPE_SOCKET_OPTIONS]
 | 
						|
 | 
						|
    timeout: None | (float)
 | 
						|
 | 
						|
    host: str
 | 
						|
    port: int
 | 
						|
    blocksize: int
 | 
						|
    source_address: tuple[str, int] | None
 | 
						|
    socket_options: _TYPE_SOCKET_OPTIONS | None
 | 
						|
 | 
						|
    proxy: Url | None
 | 
						|
    proxy_config: ProxyConfig | None
 | 
						|
 | 
						|
    is_verified: bool = False
 | 
						|
    proxy_is_verified: bool | None = None
 | 
						|
 | 
						|
    _response: EmscriptenResponse | None
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        host: str,
 | 
						|
        port: int = 0,
 | 
						|
        *,
 | 
						|
        timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
 | 
						|
        source_address: tuple[str, int] | None = None,
 | 
						|
        blocksize: int = 8192,
 | 
						|
        socket_options: _TYPE_SOCKET_OPTIONS | None = None,
 | 
						|
        proxy: Url | None = None,
 | 
						|
        proxy_config: ProxyConfig | None = None,
 | 
						|
    ) -> None:
 | 
						|
        self.host = host
 | 
						|
        self.port = port
 | 
						|
        self.timeout = timeout if isinstance(timeout, float) else 0.0
 | 
						|
        self.scheme = "http"
 | 
						|
        self._closed = True
 | 
						|
        self._response = None
 | 
						|
        # ignore these things because we don't
 | 
						|
        # have control over that stuff
 | 
						|
        self.proxy = None
 | 
						|
        self.proxy_config = None
 | 
						|
        self.blocksize = blocksize
 | 
						|
        self.source_address = None
 | 
						|
        self.socket_options = None
 | 
						|
        self.is_verified = False
 | 
						|
 | 
						|
    def set_tunnel(
 | 
						|
        self,
 | 
						|
        host: str,
 | 
						|
        port: int | None = 0,
 | 
						|
        headers: typing.Mapping[str, str] | None = None,
 | 
						|
        scheme: str = "http",
 | 
						|
    ) -> None:
 | 
						|
        pass
 | 
						|
 | 
						|
    def connect(self) -> None:
 | 
						|
        pass
 | 
						|
 | 
						|
    def request(
 | 
						|
        self,
 | 
						|
        method: str,
 | 
						|
        url: str,
 | 
						|
        body: _TYPE_BODY | None = None,
 | 
						|
        headers: typing.Mapping[str, str] | None = None,
 | 
						|
        # We know *at least* botocore is depending on the order of the
 | 
						|
        # first 3 parameters so to be safe we only mark the later ones
 | 
						|
        # as keyword-only to ensure we have space to extend.
 | 
						|
        *,
 | 
						|
        chunked: bool = False,
 | 
						|
        preload_content: bool = True,
 | 
						|
        decode_content: bool = True,
 | 
						|
        enforce_content_length: bool = True,
 | 
						|
    ) -> None:
 | 
						|
        self._closed = False
 | 
						|
        if url.startswith("/"):
 | 
						|
            # no scheme / host / port included, make a full url
 | 
						|
            url = f"{self.scheme}://{self.host}:{self.port}" + url
 | 
						|
        request = EmscriptenRequest(
 | 
						|
            url=url,
 | 
						|
            method=method,
 | 
						|
            timeout=self.timeout if self.timeout else 0,
 | 
						|
            decode_content=decode_content,
 | 
						|
        )
 | 
						|
        request.set_body(body)
 | 
						|
        if headers:
 | 
						|
            for k, v in headers.items():
 | 
						|
                request.set_header(k, v)
 | 
						|
        self._response = None
 | 
						|
        try:
 | 
						|
            if not preload_content:
 | 
						|
                self._response = send_streaming_request(request)
 | 
						|
            if self._response is None:
 | 
						|
                self._response = send_request(request)
 | 
						|
        except _TimeoutError as e:
 | 
						|
            raise TimeoutError(e.message) from e
 | 
						|
        except _RequestError as e:
 | 
						|
            raise HTTPException(e.message) from e
 | 
						|
 | 
						|
    def getresponse(self) -> BaseHTTPResponse:
 | 
						|
        if self._response is not None:
 | 
						|
            return EmscriptenHttpResponseWrapper(
 | 
						|
                internal_response=self._response,
 | 
						|
                url=self._response.request.url,
 | 
						|
                connection=self,
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            raise ResponseNotReady()
 | 
						|
 | 
						|
    def close(self) -> None:
 | 
						|
        self._closed = True
 | 
						|
        self._response = None
 | 
						|
 | 
						|
    @property
 | 
						|
    def is_closed(self) -> bool:
 | 
						|
        """Whether the connection either is brand new or has been previously closed.
 | 
						|
        If this property is True then both ``is_connected`` and ``has_connected_to_proxy``
 | 
						|
        properties must be False.
 | 
						|
        """
 | 
						|
        return self._closed
 | 
						|
 | 
						|
    @property
 | 
						|
    def is_connected(self) -> bool:
 | 
						|
        """Whether the connection is actively connected to any origin (proxy or target)"""
 | 
						|
        return True
 | 
						|
 | 
						|
    @property
 | 
						|
    def has_connected_to_proxy(self) -> bool:
 | 
						|
        """Whether the connection has successfully connected to its proxy.
 | 
						|
        This returns False if no proxy is in use. Used to determine whether
 | 
						|
        errors are coming from the proxy layer or from tunnelling to the target origin.
 | 
						|
        """
 | 
						|
        return False
 | 
						|
 | 
						|
 | 
						|
class EmscriptenHTTPSConnection(EmscriptenHTTPConnection):
 | 
						|
    default_port = port_by_scheme["https"]
 | 
						|
    # all this is basically ignored, as browser handles https
 | 
						|
    cert_reqs: int | str | None = None
 | 
						|
    ca_certs: str | None = None
 | 
						|
    ca_cert_dir: str | None = None
 | 
						|
    ca_cert_data: None | str | bytes = None
 | 
						|
    cert_file: str | None
 | 
						|
    key_file: str | None
 | 
						|
    key_password: str | None
 | 
						|
    ssl_context: typing.Any | None
 | 
						|
    ssl_version: int | str | None = None
 | 
						|
    ssl_minimum_version: int | None = None
 | 
						|
    ssl_maximum_version: int | None = None
 | 
						|
    assert_hostname: None | str | typing.Literal[False]
 | 
						|
    assert_fingerprint: str | None = None
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        host: str,
 | 
						|
        port: int = 0,
 | 
						|
        *,
 | 
						|
        timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
 | 
						|
        source_address: tuple[str, int] | None = None,
 | 
						|
        blocksize: int = 16384,
 | 
						|
        socket_options: (
 | 
						|
            None | _TYPE_SOCKET_OPTIONS
 | 
						|
        ) = HTTPConnection.default_socket_options,
 | 
						|
        proxy: Url | None = None,
 | 
						|
        proxy_config: ProxyConfig | None = None,
 | 
						|
        cert_reqs: int | str | None = None,
 | 
						|
        assert_hostname: None | str | typing.Literal[False] = None,
 | 
						|
        assert_fingerprint: str | None = None,
 | 
						|
        server_hostname: str | None = None,
 | 
						|
        ssl_context: typing.Any | None = None,
 | 
						|
        ca_certs: str | None = None,
 | 
						|
        ca_cert_dir: str | None = None,
 | 
						|
        ca_cert_data: None | str | bytes = None,
 | 
						|
        ssl_minimum_version: int | None = None,
 | 
						|
        ssl_maximum_version: int | None = None,
 | 
						|
        ssl_version: int | str | None = None,  # Deprecated
 | 
						|
        cert_file: str | None = None,
 | 
						|
        key_file: str | None = None,
 | 
						|
        key_password: str | None = None,
 | 
						|
    ) -> None:
 | 
						|
        super().__init__(
 | 
						|
            host,
 | 
						|
            port=port,
 | 
						|
            timeout=timeout,
 | 
						|
            source_address=source_address,
 | 
						|
            blocksize=blocksize,
 | 
						|
            socket_options=socket_options,
 | 
						|
            proxy=proxy,
 | 
						|
            proxy_config=proxy_config,
 | 
						|
        )
 | 
						|
        self.scheme = "https"
 | 
						|
 | 
						|
        self.key_file = key_file
 | 
						|
        self.cert_file = cert_file
 | 
						|
        self.key_password = key_password
 | 
						|
        self.ssl_context = ssl_context
 | 
						|
        self.server_hostname = server_hostname
 | 
						|
        self.assert_hostname = assert_hostname
 | 
						|
        self.assert_fingerprint = assert_fingerprint
 | 
						|
        self.ssl_version = ssl_version
 | 
						|
        self.ssl_minimum_version = ssl_minimum_version
 | 
						|
        self.ssl_maximum_version = ssl_maximum_version
 | 
						|
        self.ca_certs = ca_certs and os.path.expanduser(ca_certs)
 | 
						|
        self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir)
 | 
						|
        self.ca_cert_data = ca_cert_data
 | 
						|
 | 
						|
        self.cert_reqs = None
 | 
						|
 | 
						|
        # The browser will automatically verify all requests.
 | 
						|
        # We have no control over that setting.
 | 
						|
        self.is_verified = True
 | 
						|
 | 
						|
    def set_cert(
 | 
						|
        self,
 | 
						|
        key_file: str | None = None,
 | 
						|
        cert_file: str | None = None,
 | 
						|
        cert_reqs: int | str | None = None,
 | 
						|
        key_password: str | None = None,
 | 
						|
        ca_certs: str | None = None,
 | 
						|
        assert_hostname: None | str | typing.Literal[False] = None,
 | 
						|
        assert_fingerprint: str | None = None,
 | 
						|
        ca_cert_dir: str | None = None,
 | 
						|
        ca_cert_data: None | str | bytes = None,
 | 
						|
    ) -> None:
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
# verify that this class implements BaseHTTP(s) connection correctly
 | 
						|
if typing.TYPE_CHECKING:
 | 
						|
    _supports_http_protocol: BaseHTTPConnection = EmscriptenHTTPConnection("", 0)
 | 
						|
    _supports_https_protocol: BaseHTTPSConnection = EmscriptenHTTPSConnection("", 0)
 |