__init__.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. """
  2. Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more
  3. """
  4. from __future__ import annotations
  5. # Set default logging handler to avoid "No handler found" warnings.
  6. import logging
  7. import sys
  8. import typing
  9. import warnings
  10. from logging import NullHandler
  11. from . import exceptions
  12. from ._base_connection import _TYPE_BODY
  13. from ._collections import HTTPHeaderDict
  14. from ._version import __version__
  15. from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url
  16. from .filepost import _TYPE_FIELDS, encode_multipart_formdata
  17. from .poolmanager import PoolManager, ProxyManager, proxy_from_url
  18. from .response import BaseHTTPResponse, HTTPResponse
  19. from .util.request import make_headers
  20. from .util.retry import Retry
  21. from .util.timeout import Timeout
  22. # Ensure that Python is compiled with OpenSSL 1.1.1+
  23. # If the 'ssl' module isn't available at all that's
  24. # fine, we only care if the module is available.
  25. try:
  26. import ssl
  27. except ImportError:
  28. pass
  29. else:
  30. if not ssl.OPENSSL_VERSION.startswith("OpenSSL "): # Defensive:
  31. warnings.warn(
  32. "urllib3 v2 only supports OpenSSL 1.1.1+, currently "
  33. f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. "
  34. "See: https://github.com/urllib3/urllib3/issues/3020",
  35. exceptions.NotOpenSSLWarning,
  36. )
  37. elif ssl.OPENSSL_VERSION_INFO < (1, 1, 1): # Defensive:
  38. raise ImportError(
  39. "urllib3 v2 only supports OpenSSL 1.1.1+, currently "
  40. f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. "
  41. "See: https://github.com/urllib3/urllib3/issues/2168"
  42. )
  43. __author__ = "Andrey Petrov (andrey.petrov@shazow.net)"
  44. __license__ = "MIT"
  45. __version__ = __version__
  46. __all__ = (
  47. "HTTPConnectionPool",
  48. "HTTPHeaderDict",
  49. "HTTPSConnectionPool",
  50. "PoolManager",
  51. "ProxyManager",
  52. "HTTPResponse",
  53. "Retry",
  54. "Timeout",
  55. "add_stderr_logger",
  56. "connection_from_url",
  57. "disable_warnings",
  58. "encode_multipart_formdata",
  59. "make_headers",
  60. "proxy_from_url",
  61. "request",
  62. "BaseHTTPResponse",
  63. )
  64. logging.getLogger(__name__).addHandler(NullHandler())
  65. def add_stderr_logger(
  66. level: int = logging.DEBUG,
  67. ) -> logging.StreamHandler[typing.TextIO]:
  68. """
  69. Helper for quickly adding a StreamHandler to the logger. Useful for
  70. debugging.
  71. Returns the handler after adding it.
  72. """
  73. # This method needs to be in this __init__.py to get the __name__ correct
  74. # even if urllib3 is vendored within another package.
  75. logger = logging.getLogger(__name__)
  76. handler = logging.StreamHandler()
  77. handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
  78. logger.addHandler(handler)
  79. logger.setLevel(level)
  80. logger.debug("Added a stderr logging handler to logger: %s", __name__)
  81. return handler
  82. # ... Clean up.
  83. del NullHandler
  84. # All warning filters *must* be appended unless you're really certain that they
  85. # shouldn't be: otherwise, it's very hard for users to use most Python
  86. # mechanisms to silence them.
  87. # SecurityWarning's always go off by default.
  88. warnings.simplefilter("always", exceptions.SecurityWarning, append=True)
  89. # InsecurePlatformWarning's don't vary between requests, so we keep it default.
  90. warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True)
  91. def disable_warnings(category: type[Warning] = exceptions.HTTPWarning) -> None:
  92. """
  93. Helper for quickly disabling all urllib3 warnings.
  94. """
  95. warnings.simplefilter("ignore", category)
  96. _DEFAULT_POOL = PoolManager()
  97. def request(
  98. method: str,
  99. url: str,
  100. *,
  101. body: _TYPE_BODY | None = None,
  102. fields: _TYPE_FIELDS | None = None,
  103. headers: typing.Mapping[str, str] | None = None,
  104. preload_content: bool | None = True,
  105. decode_content: bool | None = True,
  106. redirect: bool | None = True,
  107. retries: Retry | bool | int | None = None,
  108. timeout: Timeout | float | int | None = 3,
  109. json: typing.Any | None = None,
  110. ) -> BaseHTTPResponse:
  111. """
  112. A convenience, top-level request method. It uses a module-global ``PoolManager`` instance.
  113. Therefore, its side effects could be shared across dependencies relying on it.
  114. To avoid side effects create a new ``PoolManager`` instance and use it instead.
  115. The method does not accept low-level ``**urlopen_kw`` keyword arguments.
  116. :param method:
  117. HTTP request method (such as GET, POST, PUT, etc.)
  118. :param url:
  119. The URL to perform the request on.
  120. :param body:
  121. Data to send in the request body, either :class:`str`, :class:`bytes`,
  122. an iterable of :class:`str`/:class:`bytes`, or a file-like object.
  123. :param fields:
  124. Data to encode and send in the request body.
  125. :param headers:
  126. Dictionary of custom headers to send, such as User-Agent,
  127. If-None-Match, etc.
  128. :param bool preload_content:
  129. If True, the response's body will be preloaded into memory.
  130. :param bool decode_content:
  131. If True, will attempt to decode the body based on the
  132. 'content-encoding' header.
  133. :param redirect:
  134. If True, automatically handle redirects (status codes 301, 302,
  135. 303, 307, 308). Each redirect counts as a retry. Disabling retries
  136. will disable redirect, too.
  137. :param retries:
  138. Configure the number of retries to allow before raising a
  139. :class:`~urllib3.exceptions.MaxRetryError` exception.
  140. If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
  141. :class:`~urllib3.util.retry.Retry` object for fine-grained control
  142. over different types of retries.
  143. Pass an integer number to retry connection errors that many times,
  144. but no other types of errors. Pass zero to never retry.
  145. If ``False``, then retries are disabled and any exception is raised
  146. immediately. Also, instead of raising a MaxRetryError on redirects,
  147. the redirect response will be returned.
  148. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
  149. :param timeout:
  150. If specified, overrides the default timeout for this one
  151. request. It may be a float (in seconds) or an instance of
  152. :class:`urllib3.util.Timeout`.
  153. :param json:
  154. Data to encode and send as JSON with UTF-encoded in the request body.
  155. The ``"Content-Type"`` header will be set to ``"application/json"``
  156. unless specified otherwise.
  157. """
  158. return _DEFAULT_POOL.request(
  159. method,
  160. url,
  161. body=body,
  162. fields=fields,
  163. headers=headers,
  164. preload_content=preload_content,
  165. decode_content=decode_content,
  166. redirect=redirect,
  167. retries=retries,
  168. timeout=timeout,
  169. json=json,
  170. )
  171. if sys.platform == "emscripten":
  172. from .contrib.emscripten import inject_into_urllib3 # noqa: 401
  173. inject_into_urllib3()