From 53a0562331c4a825036a347e77984d68b310fcf3 Mon Sep 17 00:00:00 2001 From: Volker Schaus Date: Sun, 23 Oct 2022 18:35:43 +0000 Subject: [PATCH 01/88] change to SPDX conform license string --- requests/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requests/__version__.py b/requests/__version__.py index e725ada655..5778594af3 100644 --- a/requests/__version__.py +++ b/requests/__version__.py @@ -9,6 +9,6 @@ __build__ = 0x022801 __author__ = "Kenneth Reitz" __author_email__ = "me@kennethreitz.org" -__license__ = "Apache 2.0" +__license__ = "Apache-2.0" __copyright__ = "Copyright 2022 Kenneth Reitz" __cake__ = "\u2728 \U0001f370 \u2728" From 6e5b15d542a4e85945fd72066bb6cecbc3a82191 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Mon, 22 May 2023 08:36:22 -0700 Subject: [PATCH 02/88] Fix linting issues --- requests/sessions.py | 2 +- tests/test_requests.py | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/requests/sessions.py b/requests/sessions.py index dbcf2a7b0e..df35bfe2cd 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -326,7 +326,7 @@ def rebuild_proxies(self, prepared_request, proxies): # urllib3 handles proxy authorization for us in the standard adapter. # Avoid appending this to TLS tunneled requests where it may be leaked. - if not scheme.startswith('https') and username and password: + if not scheme.startswith("https") and username and password: headers["Proxy-Authorization"] = _basic_auth_str(username, password) return new_proxies diff --git a/tests/test_requests.py b/tests/test_requests.py index b420c44d73..5a01f5fbb2 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -647,25 +647,26 @@ def test_proxy_authorization_preserved_on_request(self, httpbin): assert sent_headers.get("Proxy-Authorization") == proxy_auth_value - @pytest.mark.parametrize( "url,has_proxy_auth", ( - ('http://example.com', True), - ('https://example.com', False), + ("http://example.com", True), + ("https://example.com", False), ), ) - def test_proxy_authorization_not_appended_to_https_request(self, url, has_proxy_auth): + def test_proxy_authorization_not_appended_to_https_request( + self, url, has_proxy_auth + ): session = requests.Session() proxies = { - 'http': 'http://test:pass@localhost:8080', - 'https': 'http://test:pass@localhost:8090', + "http": "http://test:pass@localhost:8080", + "https": "http://test:pass@localhost:8090", } - req = requests.Request('GET', url) + req = requests.Request("GET", url) prep = req.prepare() session.rebuild_proxies(prep, proxies) - assert ('Proxy-Authorization' in prep.headers) is has_proxy_auth + assert ("Proxy-Authorization" in prep.headers) is has_proxy_auth def test_basicauth_with_netrc(self, httpbin): auth = ("user", "pass") From 22db55a8896b69e53d0a3cc2764c27b832c81478 Mon Sep 17 00:00:00 2001 From: Boris Verkhovskiy Date: Mon, 26 Jun 2023 18:09:23 +0100 Subject: [PATCH 03/88] Fix doc typo (#6467) --- requests/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requests/api.py b/requests/api.py index cd0b3eeac3..5960744552 100644 --- a/requests/api.py +++ b/requests/api.py @@ -25,7 +25,7 @@ def request(method, url, **kwargs): :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` - or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string + or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content_type'`` is a string defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers to add for the file. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. From cdbc2e271529f467b278b2760f12ee0b5d6930d3 Mon Sep 17 00:00:00 2001 From: Matthew Armand Date: Mon, 3 Jul 2023 16:38:22 -0400 Subject: [PATCH 04/88] Add an Example for automatic retries to the Advanced Usage docs (#6258) - While Requests doesn't automatically retry failures, this ability is a very common advanced use case in real world applications. - Although there's a mention of this ability on the HTTPAdapter class docs, it's a bit buried and not very specific. - It makes sense then to have an Example in the HTTPAdapter section of the Advanced Usage docs with a basic template for how this can be accomplished with Requests. --- docs/user/advanced.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index c664a83d30..055c88a956 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -1026,8 +1026,30 @@ library to use SSLv3:: num_pools=connections, maxsize=maxsize, block=block, ssl_version=ssl.PROTOCOL_SSLv3) +Example: Automatic Retries +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, Requests does not retry failed connections. However, it is possible +to implement automatic retries with a powerful array of features, including +backoff, within a Requests :class:`Session ` using the +`urllib3.util.Retry`_ class:: + + from urllib3.util import Retry + from requests import Session + from requests.adapters import HTTPAdapter + + s = Session() + retries = Retry( + total=3, + backoff_factor=0.1, + status_forcelist=[502, 503, 504], + allowed_methods={'POST'}, + ) + s.mount('https://', HTTPAdapter(max_retries=retries)) + .. _`described here`: https://kenreitz.org/essays/2012/06/14/the-future-of-python-http .. _`urllib3`: https://github.com/urllib3/urllib3 +.. _`urllib3.util.Retry`: https://urllib3.readthedocs.io/en/stable/reference/urllib3.util.html#urllib3.util.Retry .. _blocking-or-nonblocking: From fecf3dc472ddc78e20e96ea0b18e1589110c1d5e Mon Sep 17 00:00:00 2001 From: cpzt Date: Sun, 30 Jul 2023 09:01:42 +0800 Subject: [PATCH 05/88] add docstring parameter `hooks` (#6456) --- requests/sessions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requests/sessions.py b/requests/sessions.py index df35bfe2cd..2d1f8e71e0 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -545,6 +545,8 @@ def request( :type allow_redirects: bool :param proxies: (optional) Dictionary mapping protocol or protocol and hostname to the URL of the proxy. + :param hooks: (optional) Dictionary mapping hook name to one event or + list of events, event must be callable. :param stream: (optional) whether to immediately download the response content. Defaults to ``False``. :param verify: (optional) Either a boolean, in which case it controls whether we verify From 2ecdb685619340735fa85d253c4779029957246f Mon Sep 17 00:00:00 2001 From: Alexandre Erwin Ittner Date: Sat, 29 Jul 2023 22:50:43 -0300 Subject: [PATCH 06/88] Update reference to "cookielib" to "cookiejar" in documentation (#6214) --- requests/cookies.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/requests/cookies.py b/requests/cookies.py index bf54ab237e..f69d0cda9e 100644 --- a/requests/cookies.py +++ b/requests/cookies.py @@ -2,7 +2,7 @@ requests.cookies ~~~~~~~~~~~~~~~~ -Compatibility code to be able to use `cookielib.CookieJar` with requests. +Compatibility code to be able to use `http.cookiejar.CookieJar` with requests. requests.utils imports from here, so be careful with imports. """ @@ -23,7 +23,7 @@ class MockRequest: """Wraps a `requests.Request` to mimic a `urllib2.Request`. - The code in `cookielib.CookieJar` expects this interface in order to correctly + The code in `http.cookiejar.CookieJar` expects this interface in order to correctly manage cookie policies, i.e., determine whether a cookie can be set, given the domains of the request and the cookie. @@ -76,7 +76,7 @@ def get_header(self, name, default=None): return self._r.headers.get(name, self._new_headers.get(name, default)) def add_header(self, key, val): - """cookielib has no legitimate use for this method; add it back if you find one.""" + """cookiejar has no legitimate use for this method; add it back if you find one.""" raise NotImplementedError( "Cookie headers should be added with add_unredirected_header()" ) @@ -104,11 +104,11 @@ class MockResponse: """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. ...what? Basically, expose the parsed HTTP headers from the server response - the way `cookielib` expects to see them. + the way `http.cookiejar` expects to see them. """ def __init__(self, headers): - """Make a MockResponse for `cookielib` to read. + """Make a MockResponse for `cookiejar` to read. :param headers: a httplib.HTTPMessage or analogous carrying the headers """ @@ -124,7 +124,7 @@ def getheaders(self, name): def extract_cookies_to_jar(jar, request, response): """Extract the cookies from the response into a CookieJar. - :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) + :param jar: http.cookiejar.CookieJar (not necessarily a RequestsCookieJar) :param request: our own requests.Request object :param response: urllib3.HTTPResponse object """ @@ -174,7 +174,7 @@ class CookieConflictError(RuntimeError): class RequestsCookieJar(cookielib.CookieJar, MutableMapping): - """Compatibility class; is a cookielib.CookieJar, but exposes a dict + """Compatibility class; is a http.cookiejar.CookieJar, but exposes a dict interface. This is the CookieJar we create by default for requests and sessions that @@ -341,7 +341,7 @@ def __setitem__(self, name, value): self.set(name, value) def __delitem__(self, name): - """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s + """Deletes a cookie given a name. Wraps ``http.cookiejar.CookieJar``'s ``remove_cookie_by_name()``. """ remove_cookie_by_name(self, name) From dfe46c1b7f55c9377caecba2119be14d3cce74e5 Mon Sep 17 00:00:00 2001 From: Kevin Kirsche Date: Sat, 29 Jul 2023 21:55:18 -0400 Subject: [PATCH 07/88] refactor: prefer dictionary comphrension to loop (#6187) --- requests/utils.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index a367417f8e..f85f1bc614 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -466,11 +466,7 @@ def dict_from_cookiejar(cj): :rtype: dict """ - cookie_dict = {} - - for cookie in cj: - cookie_dict[cookie.name] = cookie.value - + cookie_dict = {cookie.name: cookie.value for cookie in cj} return cookie_dict From aa4cc78627bcf8ff87b73422ec06748d833c7a15 Mon Sep 17 00:00:00 2001 From: Calle Svensson Date: Sun, 30 Jul 2023 06:05:44 +0200 Subject: [PATCH 08/88] Add note about adapter prefix match to docs (#6465) --- docs/user/advanced.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 055c88a956..543b378511 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -994,6 +994,10 @@ The mount call registers a specific instance of a Transport Adapter to a prefix. Once mounted, any HTTP request made using that session whose URL starts with the given prefix will use the given Transport Adapter. +.. note:: The adapter will be chosen based on a longest prefix match. Be mindful + prefixes such as ``http://localhost`` will also match ``http://localhost.other.com`` + or ``http://localhost@other.com``. It's recommended to terminate full hostnames with a ``/``. + Many of the details of implementing a Transport Adapter are beyond the scope of this documentation, but take a look at the next example for a simple SSL use- case. For more than that, you might look at subclassing the From cb7fcd7ebddb45917fb7a526d3627feb2d7738b9 Mon Sep 17 00:00:00 2001 From: Joren Vrancken Date: Sat, 12 Aug 2023 19:53:36 +0200 Subject: [PATCH 09/88] Specify that Session.headers needs to be set to a OrderedDict in Header Ordering docs (#6475) --- docs/user/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 543b378511..c90a13dc6d 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -1081,7 +1081,7 @@ Header Ordering In unusual circumstances you may want to provide headers in an ordered manner. If you pass an ``OrderedDict`` to the ``headers`` keyword argument, that will provide the headers with an ordering. *However*, the ordering of the default headers used by Requests will be preferred, which means that if you override default headers in the ``headers`` keyword argument, they may appear out of order compared to other headers in that keyword argument. -If this is problematic, users should consider setting the default headers on a :class:`Session ` object, by setting :attr:`Session ` to a custom ``OrderedDict``. That ordering will always be preferred. +If this is problematic, users should consider setting the default headers on a :class:`Session ` object, by setting :attr:`Session.headers ` to a custom ``OrderedDict``. That ordering will always be preferred. .. _timeouts: From 2c193bda0c50481d3bff4ef4d90203c578afa294 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Sat, 12 Aug 2023 12:02:58 -0700 Subject: [PATCH 10/88] Pin GHA workflows and add dependabot to keep them up to date (#6497) --- .github/dependabot.yml | 11 +++++++++++ .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/lint.yml | 6 +++--- .github/workflows/lock-issues.yml | 2 +- .github/workflows/run-tests.yml | 4 ++-- 5 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..2be85338e3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + ignore: + # Ignore all patch releases as we can manually + # upgrade if we run into a bug and need a fix. + - dependency-name: "*" + update-types: ["version-update:semver-patch"] diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1e7dba233b..fc6ae0f8fa 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@231aa2c8a89117b126725a0e11897209b7118144 # v1.1.39 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@231aa2c8a89117b126725a0e11897209b7118144 # v1.1.39 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@231aa2c8a89117b126725a0e11897209b7118144 # v1.1.39 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index df275c51b6..b439153aee 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,10 +11,10 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: "3.x" - name: Run pre-commit - uses: pre-commit/action@v3.0.0 + uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507 # v3.0.0 diff --git a/.github/workflows/lock-issues.yml b/.github/workflows/lock-issues.yml index f8429c3fdc..1bc88507d9 100644 --- a/.github/workflows/lock-issues.yml +++ b/.github/workflows/lock-issues.yml @@ -13,7 +13,7 @@ jobs: if: github.repository_owner == 'psf' runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v3 + - uses: dessant/lock-threads@e460dfeb36e731f3aeb214be6b0c9a9d9a67eda6 # v3.0.0 with: issue-lock-inactive-days: 90 pr-lock-inactive-days: 90 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c4159508e4..978ab7bd5e 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -21,9 +21,9 @@ jobs: os: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@e9aba2c848f5ebd159c070c61ea2c4e2b122355e # v2.3.4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From 8112fcc7beb15e1cdc66180c10a3290174866828 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Sat, 12 Aug 2023 12:03:10 -0700 Subject: [PATCH 11/88] Pre commit update (#6498) --- .pre-commit-config.yaml | 8 ++++---- requests/adapters.py | 1 - requests/auth.py | 1 - requests/models.py | 6 ++---- requests/sessions.py | 8 ++------ requests/utils.py | 1 + tests/test_requests.py | 13 ------------- 7 files changed, 9 insertions(+), 29 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5b915dc383..0a0515cf87 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ exclude: 'docs/|ext/' repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.4.0 hooks: - id: check-yaml - id: debug-statements @@ -13,16 +13,16 @@ repos: hooks: - id: isort - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 23.7.0 hooks: - id: black exclude: tests/test_lowlevel.py - repo: https://github.com/asottile/pyupgrade - rev: v2.31.1 + rev: v3.10.1 hooks: - id: pyupgrade args: [--py37-plus] - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 diff --git a/requests/adapters.py b/requests/adapters.py index 78e3bb6ecf..eb240fa954 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -247,7 +247,6 @@ def cert_verify(self, conn, url, verify, cert): :param cert: The SSL certificate to verify. """ if url.lower().startswith("https") and verify: - cert_loc = None # Allow self-specified cert location. diff --git a/requests/auth.py b/requests/auth.py index 9733686ddb..4a7ce6dc14 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -258,7 +258,6 @@ def handle_401(self, r, **kwargs): s_auth = r.headers.get("www-authenticate", "") if "digest" in s_auth.lower() and self._thread_local.num_401_calls < 2: - self._thread_local.num_401_calls += 1 pat = re.compile(r"digest ", flags=re.IGNORECASE) self._thread_local.chal = parse_dict_header(pat.sub("", s_auth, count=1)) diff --git a/requests/models.py b/requests/models.py index 617a4134e5..44556394ec 100644 --- a/requests/models.py +++ b/requests/models.py @@ -170,7 +170,7 @@ def _encode_files(files, data): ) ) - for (k, v) in files: + for k, v in files: # support for explicit filename ft = None fh = None @@ -268,7 +268,6 @@ def __init__( hooks=None, json=None, ): - # Default empty dicts for dict params. data = [] if data is None else data files = [] if files is None else files @@ -277,7 +276,7 @@ def __init__( hooks = {} if hooks is None else hooks self.hooks = default_hooks() - for (k, v) in list(hooks.items()): + for k, v in list(hooks.items()): self.register_hook(event=k, hook=v) self.method = method @@ -865,7 +864,6 @@ def iter_lines( for chunk in self.iter_content( chunk_size=chunk_size, decode_unicode=decode_unicode ): - if pending is not None: chunk = pending + chunk diff --git a/requests/sessions.py b/requests/sessions.py index 2d1f8e71e0..b387bc36df 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -262,7 +262,6 @@ def resolve_redirects( if yield_requests: yield req else: - resp = self.send( req, stream=stream, @@ -389,7 +388,6 @@ class Session(SessionRedirectMixin): ] def __init__(self): - #: A case-insensitive dictionary of headers to be sent on each #: :class:`Request ` sent from this #: :class:`Session `. @@ -713,7 +711,6 @@ def send(self, request, **kwargs): # Persist cookies if r.history: - # If the hooks create history then we want those cookies too for resp in r.history: extract_cookies_to_jar(self.cookies, resp.request, resp.raw) @@ -761,7 +758,7 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert): # Set environment's proxies. no_proxy = proxies.get("no_proxy") if proxies is not None else None env_proxies = get_environ_proxies(url, no_proxy=no_proxy) - for (k, v) in env_proxies.items(): + for k, v in env_proxies.items(): proxies.setdefault(k, v) # Look for requests environment configuration @@ -787,8 +784,7 @@ def get_adapter(self, url): :rtype: requests.adapters.BaseAdapter """ - for (prefix, adapter) in self.adapters.items(): - + for prefix, adapter in self.adapters.items(): if url.lower().startswith(prefix.lower()): return adapter diff --git a/requests/utils.py b/requests/utils.py index f85f1bc614..1ae77d68ff 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -763,6 +763,7 @@ def should_bypass_proxies(url, no_proxy): :rtype: bool """ + # Prioritize lowercase environment variables over uppercase # to keep a consistent behaviour with other http projects (curl, wget). def get_proxy(key): diff --git a/tests/test_requests.py b/tests/test_requests.py index 5a01f5fbb2..6e831a91e7 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -75,11 +75,9 @@ class TestRequests: - digest_auth_algo = ("MD5", "SHA-256", "SHA-512") def test_entry_points(self): - requests.session requests.session().get requests.session().head @@ -510,7 +508,6 @@ def test_headers_preserve_order(self, httpbin): @pytest.mark.parametrize("key", ("User-agent", "user-agent")) def test_user_agent_transfers(self, httpbin, key): - heads = {key: "Mozilla/5.0 (github.com/psf/requests)"} r = requests.get(httpbin("user-agent"), headers=heads) @@ -704,7 +701,6 @@ def get_netrc_auth_mock(url): requests.sessions.get_netrc_auth = old_auth def test_DIGEST_HTTP_200_OK_GET(self, httpbin): - for authtype in self.digest_auth_algo: auth = HTTPDigestAuth("user", "pass") url = httpbin("digest-auth", "auth", "user", "pass", authtype, "never") @@ -722,7 +718,6 @@ def test_DIGEST_HTTP_200_OK_GET(self, httpbin): assert r.status_code == 200 def test_DIGEST_AUTH_RETURNS_COOKIE(self, httpbin): - for authtype in self.digest_auth_algo: url = httpbin("digest-auth", "auth", "user", "pass", authtype) auth = HTTPDigestAuth("user", "pass") @@ -733,7 +728,6 @@ def test_DIGEST_AUTH_RETURNS_COOKIE(self, httpbin): assert r.status_code == 200 def test_DIGEST_AUTH_SETS_SESSION_COOKIES(self, httpbin): - for authtype in self.digest_auth_algo: url = httpbin("digest-auth", "auth", "user", "pass", authtype) auth = HTTPDigestAuth("user", "pass") @@ -742,7 +736,6 @@ def test_DIGEST_AUTH_SETS_SESSION_COOKIES(self, httpbin): assert s.cookies["fake"] == "fake_value" def test_DIGEST_STREAM(self, httpbin): - for authtype in self.digest_auth_algo: auth = HTTPDigestAuth("user", "pass") url = httpbin("digest-auth", "auth", "user", "pass", authtype) @@ -754,7 +747,6 @@ def test_DIGEST_STREAM(self, httpbin): assert r.raw.read() == b"" def test_DIGESTAUTH_WRONG_HTTP_401_GET(self, httpbin): - for authtype in self.digest_auth_algo: auth = HTTPDigestAuth("user", "wrongpass") url = httpbin("digest-auth", "auth", "user", "pass", authtype) @@ -771,7 +763,6 @@ def test_DIGESTAUTH_WRONG_HTTP_401_GET(self, httpbin): assert r.status_code == 401 def test_DIGESTAUTH_QUOTES_QOP_VALUE(self, httpbin): - for authtype in self.digest_auth_algo: auth = HTTPDigestAuth("user", "pass") url = httpbin("digest-auth", "auth", "user", "pass", authtype) @@ -780,7 +771,6 @@ def test_DIGESTAUTH_QUOTES_QOP_VALUE(self, httpbin): assert '"auth"' in r.request.headers["Authorization"] def test_POSTBIN_GET_POST_FILES(self, httpbin): - url = httpbin("post") requests.post(url).raise_for_status() @@ -798,7 +788,6 @@ def test_POSTBIN_GET_POST_FILES(self, httpbin): requests.post(url, files=["bad file data"]) def test_invalid_files_input(self, httpbin): - url = httpbin("post") post = requests.post(url, files={"random-file-1": None, "random-file-2": 1}) assert b'name="random-file-1"' not in post.request.body @@ -846,7 +835,6 @@ def seek(self, offset, where=0): assert post2.json()["data"] == "st" def test_POSTBIN_GET_POST_FILES_WITH_DATA(self, httpbin): - url = httpbin("post") requests.post(url).raise_for_status() @@ -1035,7 +1023,6 @@ def test_certificate_failure(self, httpbin_secure): requests.get(httpbin_secure("status", "200")) def test_urlencoded_get_query_multivalued_param(self, httpbin): - r = requests.get(httpbin("get"), params={"test": ["foo", "baz"]}) assert r.status_code == 200 assert r.url == httpbin("get?test=foo&test=baz") From ea49261a279c9e8216f25410a9e9611b758c2611 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 19:03:17 +0000 Subject: [PATCH 12/88] Bump dessant/lock-threads from 3.0.0 to 4.0.1 Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 3.0.0 to 4.0.1. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/main/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/e460dfeb36e731f3aeb214be6b0c9a9d9a67eda6...be8aa5be94131386884a6da4189effda9b14aa21) --- updated-dependencies: - dependency-name: dessant/lock-threads dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lock-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock-issues.yml b/.github/workflows/lock-issues.yml index 1bc88507d9..66f68a1900 100644 --- a/.github/workflows/lock-issues.yml +++ b/.github/workflows/lock-issues.yml @@ -13,7 +13,7 @@ jobs: if: github.repository_owner == 'psf' runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@e460dfeb36e731f3aeb214be6b0c9a9d9a67eda6 # v3.0.0 + - uses: dessant/lock-threads@be8aa5be94131386884a6da4189effda9b14aa21 # v4.0.1 with: issue-lock-inactive-days: 90 pr-lock-inactive-days: 90 From c7933453cff05a297d4d1cdacb7fb49480e6924c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 19:03:22 +0000 Subject: [PATCH 13/88] Bump actions/setup-python from 2.3.4 to 4.7.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.4 to 4.7.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.3.4...61a6322f88396a6271a6ee3565807d608ecaddd1) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 978ab7bd5e..01028d5cb3 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@e9aba2c848f5ebd159c070c61ea2c4e2b122355e # v2.3.4 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From 9acca90bf6bdb29f80b9c82ff66303bd6fb157fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 19:03:30 +0000 Subject: [PATCH 14/88] Bump github/codeql-action from 1.1.39 to 2.21.3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1.1.39 to 2.21.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/231aa2c8a89117b126725a0e11897209b7118144...5b6282e01c62d02e720b81eb8a51204f527c3624) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fc6ae0f8fa..1a58bb8f7e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@231aa2c8a89117b126725a0e11897209b7118144 # v1.1.39 + uses: github/codeql-action/init@5b6282e01c62d02e720b81eb8a51204f527c3624 # v2.21.3 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@231aa2c8a89117b126725a0e11897209b7118144 # v1.1.39 + uses: github/codeql-action/autobuild@5b6282e01c62d02e720b81eb8a51204f527c3624 # v2.21.3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@231aa2c8a89117b126725a0e11897209b7118144 # v1.1.39 + uses: github/codeql-action/analyze@5b6282e01c62d02e720b81eb8a51204f527c3624 # v2.21.3 From 4bd06cd325f4b7213708ff520f346c177ba218d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 19:37:22 +0000 Subject: [PATCH 15/88] Bump actions/checkout from 2.7.0 to 3.5.3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.7.0 to 3.5.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2.7.0...c85c95e3d7251135ab7dc9ce3241c5835cc595a9) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fc6ae0f8fa..80d4707ca6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 01028d5cb3..d6197a6de3 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -21,7 +21,7 @@ jobs: os: ubuntu-latest steps: - - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: From 678fca84238e311ffba758d90879d4b870030498 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Sun, 13 Aug 2023 09:56:53 -0700 Subject: [PATCH 16/88] Upgrade to httpbin 0.10.0 (#6496) --- .github/workflows/run-tests.yml | 1 + requirements-dev.txt | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d6197a6de3..4a151601f0 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -26,6 +26,7 @@ jobs: uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} + cache: 'pip' - name: Install dependencies run: | make diff --git a/requirements-dev.txt b/requirements-dev.txt index d62637378e..c24a6bc6d4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,11 +3,7 @@ pytest>=2.8.0,<=6.2.5 pytest-cov pytest-httpbin==2.0.0 pytest-mock==2.0.0 -httpbin==0.7.0 +httpbin==0.10.0 trustme wheel cryptography<40.0.0; python_version <= '3.7' and platform_python_implementation == 'PyPy' - -# Flask Stack -Flask>1.0,<2.0 -markupsafe<2.1 From e9fa2e2da3076e4f55f18b3f4a169c7b3916b272 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Sun, 13 Aug 2023 12:56:18 -0700 Subject: [PATCH 17/88] Add 3.12 classifier and tox configuration (#6503) --- setup.py | 1 + tox.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 012354574d..e93bb41622 100755 --- a/setup.py +++ b/setup.py @@ -112,6 +112,7 @@ def run_tests(self): "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", diff --git a/tox.ini b/tox.ini index 546c7371b1..92ab6d1a24 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{37,38,39,310,311}-{default, use_chardet_on_py3} +envlist = py{37,38,39,310,311,312}-{default, use_chardet_on_py3} [testenv] deps = -rrequirements-dev.txt From d63e94f552ebf77ccf45d97e5863ac46500fa2c7 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Sun, 13 Aug 2023 14:46:13 -0700 Subject: [PATCH 18/88] Move to src directory (#6506) --- Makefile | 10 +++++----- pyproject.toml | 7 ++----- setup.cfg | 4 ++-- setup.py | 4 ++-- {requests => src/requests}/__init__.py | 0 {requests => src/requests}/__version__.py | 0 {requests => src/requests}/_internal_utils.py | 0 {requests => src/requests}/adapters.py | 0 {requests => src/requests}/api.py | 0 {requests => src/requests}/auth.py | 0 {requests => src/requests}/certs.py | 0 {requests => src/requests}/compat.py | 0 {requests => src/requests}/cookies.py | 0 {requests => src/requests}/exceptions.py | 0 {requests => src/requests}/help.py | 0 {requests => src/requests}/hooks.py | 0 {requests => src/requests}/models.py | 0 {requests => src/requests}/packages.py | 0 {requests => src/requests}/sessions.py | 0 {requests => src/requests}/status_codes.py | 0 {requests => src/requests}/structures.py | 0 {requests => src/requests}/utils.py | 0 22 files changed, 11 insertions(+), 14 deletions(-) rename {requests => src/requests}/__init__.py (100%) rename {requests => src/requests}/__version__.py (100%) rename {requests => src/requests}/_internal_utils.py (100%) rename {requests => src/requests}/adapters.py (100%) rename {requests => src/requests}/api.py (100%) rename {requests => src/requests}/auth.py (100%) rename {requests => src/requests}/certs.py (100%) rename {requests => src/requests}/compat.py (100%) rename {requests => src/requests}/cookies.py (100%) rename {requests => src/requests}/exceptions.py (100%) rename {requests => src/requests}/help.py (100%) rename {requests => src/requests}/hooks.py (100%) rename {requests => src/requests}/models.py (100%) rename {requests => src/requests}/packages.py (100%) rename {requests => src/requests}/sessions.py (100%) rename {requests => src/requests}/status_codes.py (100%) rename {requests => src/requests}/structures.py (100%) rename {requests => src/requests}/utils.py (100%) diff --git a/Makefile b/Makefile index f74dc42ddf..192b926853 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,23 @@ .PHONY: docs init: - pip install -r requirements-dev.txt + python -m pip install -r requirements-dev.txt test: # This runs all of the tests on all supported Python versions. tox -p ci: - pytest tests --junitxml=report.xml + python -m pytest tests --junitxml=report.xml test-readme: python setup.py check --restructuredtext --strict && ([ $$? -eq 0 ] && echo "README.rst and HISTORY.rst ok") || echo "Invalid markup in README.rst or HISTORY.rst!" flake8: - flake8 --ignore=E501,F401,E128,E402,E731,F821 requests + python -m flake8 src/requests coverage: - pytest --cov-config .coveragerc --verbose --cov-report term --cov-report xml --cov=requests tests + python -m pytest --cov-config .coveragerc --verbose --cov-report term --cov-report xml --cov=src/requests tests publish: - pip install 'twine>=1.5.0' + python -m pip install 'twine>=1.5.0' python setup.py sdist bdist_wheel twine upload dist/* rm -fr build dist .egg requests.egg-info diff --git a/pyproject.toml b/pyproject.toml index d3ab7bd9bb..1b7901e155 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,10 @@ [tool.isort] profile = "black" -src_paths = ["requests", "test"] +src_paths = ["src/requests", "test"] honor_noqa = true [tool.pytest.ini_options] addopts = "--doctest-modules" doctest_optionflags = "NORMALIZE_WHITESPACE ELLIPSIS" minversion = "6.2" -testpaths = [ - "requests", - "tests", -] +testpaths = ["tests"] diff --git a/setup.cfg b/setup.cfg index bf21c81cc0..14e2d96cf6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,6 +12,6 @@ requires-dist = [flake8] ignore = E203, E501, W503 per-file-ignores = - requests/__init__.py:E402, F401 - requests/compat.py:E402, F401 + src/requests/__init__.py:E402, F401 + src/requests/compat.py:E402, F401 tests/compat.py:F401 diff --git a/setup.py b/setup.py index e93bb41622..dc8043a695 100755 --- a/setup.py +++ b/setup.py @@ -75,7 +75,7 @@ def run_tests(self): about = {} here = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(here, "requests", "__version__.py"), "r", "utf-8") as f: +with open(os.path.join(here, "src", "requests", "__version__.py"), "r", "utf-8") as f: exec(f.read(), about) with open("README.md", "r", "utf-8") as f: @@ -92,7 +92,7 @@ def run_tests(self): url=about["__url__"], packages=["requests"], package_data={"": ["LICENSE", "NOTICE"]}, - package_dir={"requests": "requests"}, + package_dir={"": "src"}, include_package_data=True, python_requires=">=3.7", install_requires=requires, diff --git a/requests/__init__.py b/src/requests/__init__.py similarity index 100% rename from requests/__init__.py rename to src/requests/__init__.py diff --git a/requests/__version__.py b/src/requests/__version__.py similarity index 100% rename from requests/__version__.py rename to src/requests/__version__.py diff --git a/requests/_internal_utils.py b/src/requests/_internal_utils.py similarity index 100% rename from requests/_internal_utils.py rename to src/requests/_internal_utils.py diff --git a/requests/adapters.py b/src/requests/adapters.py similarity index 100% rename from requests/adapters.py rename to src/requests/adapters.py diff --git a/requests/api.py b/src/requests/api.py similarity index 100% rename from requests/api.py rename to src/requests/api.py diff --git a/requests/auth.py b/src/requests/auth.py similarity index 100% rename from requests/auth.py rename to src/requests/auth.py diff --git a/requests/certs.py b/src/requests/certs.py similarity index 100% rename from requests/certs.py rename to src/requests/certs.py diff --git a/requests/compat.py b/src/requests/compat.py similarity index 100% rename from requests/compat.py rename to src/requests/compat.py diff --git a/requests/cookies.py b/src/requests/cookies.py similarity index 100% rename from requests/cookies.py rename to src/requests/cookies.py diff --git a/requests/exceptions.py b/src/requests/exceptions.py similarity index 100% rename from requests/exceptions.py rename to src/requests/exceptions.py diff --git a/requests/help.py b/src/requests/help.py similarity index 100% rename from requests/help.py rename to src/requests/help.py diff --git a/requests/hooks.py b/src/requests/hooks.py similarity index 100% rename from requests/hooks.py rename to src/requests/hooks.py diff --git a/requests/models.py b/src/requests/models.py similarity index 100% rename from requests/models.py rename to src/requests/models.py diff --git a/requests/packages.py b/src/requests/packages.py similarity index 100% rename from requests/packages.py rename to src/requests/packages.py diff --git a/requests/sessions.py b/src/requests/sessions.py similarity index 100% rename from requests/sessions.py rename to src/requests/sessions.py diff --git a/requests/status_codes.py b/src/requests/status_codes.py similarity index 100% rename from requests/status_codes.py rename to src/requests/status_codes.py diff --git a/requests/structures.py b/src/requests/structures.py similarity index 100% rename from requests/structures.py rename to src/requests/structures.py diff --git a/requests/utils.py b/src/requests/utils.py similarity index 100% rename from requests/utils.py rename to src/requests/utils.py From 005571d1180835eb5266a3fdbdbe8fdae57d90c2 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Sun, 13 Aug 2023 16:08:21 -0700 Subject: [PATCH 19/88] Remove pytest-mock requirement (#6505) --- requirements-dev.txt | 1 - tests/test_help.py | 14 ++++++++------ tests/test_requests.py | 31 +++++++++++++++---------------- tests/test_utils.py | 9 +++++---- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index c24a6bc6d4..f137c46a33 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,6 @@ pytest>=2.8.0,<=6.2.5 pytest-cov pytest-httpbin==2.0.0 -pytest-mock==2.0.0 httpbin==0.10.0 trustme wheel diff --git a/tests/test_help.py b/tests/test_help.py index fb4e967c53..5fca6207ef 100644 --- a/tests/test_help.py +++ b/tests/test_help.py @@ -1,3 +1,5 @@ +from unittest import mock + from requests.help import info @@ -11,15 +13,15 @@ def __init__(self, version): self.__version__ = version -def test_idna_without_version_attribute(mocker): +def test_idna_without_version_attribute(): """Older versions of IDNA don't provide a __version__ attribute, verify that if we have such a package, we don't blow up. """ - mocker.patch("requests.help.idna", new=None) - assert info()["idna"] == {"version": ""} + with mock.patch("requests.help.idna", new=None): + assert info()["idna"] == {"version": ""} -def test_idna_with_version_attribute(mocker): +def test_idna_with_version_attribute(): """Verify we're actually setting idna version when it should be available.""" - mocker.patch("requests.help.idna", new=VersionedPackage("2.6")) - assert info()["idna"] == {"version": "2.6"} + with mock.patch("requests.help.idna", new=VersionedPackage("2.6")): + assert info()["idna"] == {"version": "2.6"} diff --git a/tests/test_requests.py b/tests/test_requests.py index 6e831a91e7..5d8d2cd3af 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -8,6 +8,7 @@ import pickle import re import warnings +from unittest import mock import pytest import urllib3 @@ -972,12 +973,12 @@ def test_invalid_ssl_certificate_files(self, httpbin_secure): ), ), ) - def test_env_cert_bundles(self, httpbin, mocker, env, expected): + def test_env_cert_bundles(self, httpbin, env, expected): s = requests.Session() - mocker.patch("os.environ", env) - settings = s.merge_environment_settings( - url=httpbin("get"), proxies={}, stream=False, verify=True, cert=None - ) + with mock.patch("os.environ", env): + settings = s.merge_environment_settings( + url=httpbin("get"), proxies={}, stream=False, verify=True, cert=None + ) assert settings["verify"] == expected def test_http_with_certificate(self, httpbin): @@ -1464,11 +1465,9 @@ def test_response_chunk_size_type(self): (urllib3.exceptions.SSLError, tuple(), RequestsSSLError), ), ) - def test_iter_content_wraps_exceptions( - self, httpbin, mocker, exception, args, expected - ): + def test_iter_content_wraps_exceptions(self, httpbin, exception, args, expected): r = requests.Response() - r.raw = mocker.Mock() + r.raw = mock.Mock() # ReadTimeoutError can't be initialized by mock # so we'll manually create the instance with args r.raw.stream.side_effect = exception(*args) @@ -2093,16 +2092,16 @@ def test_response_iter_lines_reentrant(self, httpbin): next(r.iter_lines()) assert len(list(r.iter_lines())) == 3 - def test_session_close_proxy_clear(self, mocker): + def test_session_close_proxy_clear(self): proxies = { - "one": mocker.Mock(), - "two": mocker.Mock(), + "one": mock.Mock(), + "two": mock.Mock(), } session = requests.Session() - mocker.patch.dict(session.adapters["http://"].proxy_manager, proxies) - session.close() - proxies["one"].clear.assert_called_once_with() - proxies["two"].clear.assert_called_once_with() + with mock.patch.dict(session.adapters["http://"].proxy_manager, proxies): + session.close() + proxies["one"].clear.assert_called_once_with() + proxies["two"].clear.assert_called_once_with() def test_proxy_auth(self): adapter = HTTPAdapter() diff --git a/tests/test_utils.py b/tests/test_utils.py index 112bbd1eaf..8988eaf69c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,6 +5,7 @@ import zipfile from collections import deque from io import BytesIO +from unittest import mock import pytest @@ -751,13 +752,13 @@ def test_should_bypass_proxies(url, expected, monkeypatch): ("http://user:pass@hostname:5000", "hostname"), ), ) -def test_should_bypass_proxies_pass_only_hostname(url, expected, mocker): +def test_should_bypass_proxies_pass_only_hostname(url, expected): """The proxy_bypass function should be called with a hostname or IP without a port number or auth credentials. """ - proxy_bypass = mocker.patch("requests.utils.proxy_bypass") - should_bypass_proxies(url, no_proxy=None) - proxy_bypass.assert_called_once_with(expected) + with mock.patch("requests.utils.proxy_bypass") as proxy_bypass: + should_bypass_proxies(url, no_proxy=None) + proxy_bypass.assert_called_once_with(expected) @pytest.mark.parametrize( From 89f0eb91b396619db6695b64e368950e36bdbe7f Mon Sep 17 00:00:00 2001 From: Jonas Schell Date: Wed, 16 Aug 2023 17:16:53 +0200 Subject: [PATCH 20/88] fix monthly download badge (#6507) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c90ef08a5e..c4b170e70f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Requests allows you to send HTTP/1.1 requests extremely easily. There’s no nee Requests is one of the most downloaded Python packages today, pulling in around `30M downloads / week`— according to GitHub, Requests is currently [depended upon](https://github.com/psf/requests/network/dependents?package_id=UGFja2FnZS01NzA4OTExNg%3D%3D) by `1,000,000+` repositories. You may certainly put your trust in this code. -[![Downloads](https://pepy.tech/badge/requests/month)](https://pepy.tech/project/requests) +[![Downloads](https://static.pepy.tech/badge/requests/month)](https://pepy.tech/project/requests) [![Supported Versions](https://img.shields.io/pypi/pyversions/requests.svg)](https://pypi.org/project/requests) [![Contributors](https://img.shields.io/github/contributors/psf/requests.svg)](https://github.com/psf/requests/graphs/contributors) From 2ee5b0b01c9e7c14217a536886b337d6f08b9aac Mon Sep 17 00:00:00 2001 From: 13steinj <13steinj@users.noreply.github.com> Date: Fri, 18 Aug 2023 12:01:26 -0500 Subject: [PATCH 21/88] Fix documentation monthly download badge (#6508) --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 306b60f3ea..50b0adc3d2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,7 +9,7 @@ Requests: HTTP for Humans™ Release v\ |version|. (:ref:`Installation `) -.. image:: https://pepy.tech/badge/requests/month +.. image:: https://static.pepy.tech/badge/requests/month :target: https://pepy.tech/project/requests :alt: Requests Downloads Per Month Badge From bea231b033d643a6c4152a5b12c3e0b2524ed48f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:12:37 +0000 Subject: [PATCH 22/88] Bump actions/checkout from 3.5.3 to 3.6.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/c85c95e3d7251135ab7dc9ce3241c5835cc595a9...f43a0e5ff2bd294095638e18286ca9a3d1956744) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f64eeadc26..274de9808b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b439153aee..fcb73eb0ef 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Set up Python uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4a151601f0..d9b4741786 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -21,7 +21,7 @@ jobs: os: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: From 4585a7fbdaaebf19d213eb16326afae2e9382abe Mon Sep 17 00:00:00 2001 From: "Johnny.H" Date: Tue, 29 Aug 2023 13:41:49 +0800 Subject: [PATCH 23/88] remove pytest.ini since it does not exist anymore --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 633be369e2..87a23ab937 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ -include README.md LICENSE NOTICE HISTORY.md pytest.ini requirements-dev.txt +include README.md LICENSE NOTICE HISTORY.md requirements-dev.txt recursive-include tests *.py From 29fc8d1e9346a29b91513547d626e23f4c36e557 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:21:27 +0000 Subject: [PATCH 24/88] Bump actions/checkout from 3.6.0 to 4.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...3df4ab11eba7bda6032a0b82a6bb43b11571feac) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 274de9808b..a4dfacdf96 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fcb73eb0ef..00a8ddafe0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Set up Python uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d9b4741786..0214e32f9f 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -21,7 +21,7 @@ jobs: os: ubuntu-latest steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: From 6c8d9b1d0fd6bef2e7b617bcb1574e69c4fc8780 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 13 Sep 2023 09:33:58 -0500 Subject: [PATCH 25/88] Autoclose specific issue templates We spend a fair amount of time closing issues because people don't read the template closely or understand what they're being told. Let's take advantage of being able to auto-label an issue based on the template and then trigger a workflow to auto-magically close the issue with a message and lock the issue. --- .github/ISSUE_TEMPLATE/Custom.md | 3 ++ .github/ISSUE_TEMPLATE/Feature_request.md | 3 ++ .github/workflows/close-issues.yml | 35 +++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 .github/workflows/close-issues.yml diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index 19291c1500..332c3aea97 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -1,6 +1,9 @@ --- name: Request for Help about: Guidance on using Requests. +labels: +- "Question/Not a bug" +- "actions/autoclose-qa" --- diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index dcf6a445fb..544113ae1c 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -1,6 +1,9 @@ --- name: Feature request about: Suggest an idea for this project +labels: +- "Feature Request" +- "actions/autoclose-feat" --- diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml new file mode 100644 index 0000000000..6b3d621013 --- /dev/null +++ b/.github/workflows/close-issues.yml @@ -0,0 +1,35 @@ +name: 'Autoclose Issues' + +on: + issues: + types: + - labeled + +permissions: + issues: write + +jobs: + close_qa: + if: github.event.label.name == 'actions/autoclose-qa' + runs-on: ubuntu-latest + steps: + - env: + GITHUB_TOKEN: ${{ secrets.MY_TOKEN }} + ISSUE_URL: ${{ github.event.issue.html_url }} + run: | + gh issue close $ISSUE_URL \ + --comment "As described in the template, this is not the appropriate place for questions. Please use Stack Overflow" \ + --reason completed + gh issue lock $ISSUE_URL --reason off_topic + close_feature_request: + if: github.event.label.name == 'actions/autoclose-feat' + runs-on: ubuntu-latest + steps: + - env: + GITHUB_TOKEN: ${{ secrets.MY_TOKEN }} + ISSUE_URL: ${{ github.event.issue.html_url }} + run: | + gh issue close $ISSUE_URL \ + --comment "As described in the template, Requests is not accepting feature requests" \ + --reason "not planned" + gh issue lock $ISSUE_URL --reason off_topic From a775435c4b3ecb9f8f49b91ccb5403a071a0a4ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:28:35 +0000 Subject: [PATCH 26/88] Bump actions/checkout from 4.0.0 to 4.1.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/3df4ab11eba7bda6032a0b82a6bb43b11571feac...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a4dfacdf96..65d312f4d0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 00a8ddafe0..3a358a290a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: Set up Python uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 0214e32f9f..5461ccddfb 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -21,7 +21,7 @@ jobs: os: ubuntu-latest steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: From f5a7aefc2dc123c65ec1c6d3e83949999b03876b Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Fri, 6 Oct 2023 15:34:24 -0700 Subject: [PATCH 27/88] Fix urllib3 pin in setup.cfg (#6545) --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 14e2d96cf6..8d44e0e14b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,7 +7,7 @@ requires-dist = certifi>=2017.4.17 charset_normalizer>=2,<4 idna>=2.5,<4 - urllib3>=1.21.1,<1.27 + urllib3>=1.21.1,<3 [flake8] ignore = E203, E501, W503 From 42a3b5cce8336c52ad7102a3a493576ba40fb4fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:29:55 +0000 Subject: [PATCH 28/88] Bump github/codeql-action from 2.21.3 to 2.22.1 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.3 to 2.22.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5b6282e01c62d02e720b81eb8a51204f527c3624...fdcae64e1484d349b3366718cdfef3d404390e85) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 65d312f4d0..a2a43cfcde 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5b6282e01c62d02e720b81eb8a51204f527c3624 # v2.21.3 + uses: github/codeql-action/init@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@5b6282e01c62d02e720b81eb8a51204f527c3624 # v2.21.3 + uses: github/codeql-action/autobuild@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5b6282e01c62d02e720b81eb8a51204f527c3624 # v2.21.3 + uses: github/codeql-action/analyze@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 From f75b9504fc8427c1617bac2dd1e1aa405c9f1b1b Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 11 Oct 2023 08:19:14 -0500 Subject: [PATCH 29/88] Update close comment Co-authored-by: Nate Prewitt --- .github/workflows/close-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml index 6b3d621013..29fcde7439 100644 --- a/.github/workflows/close-issues.yml +++ b/.github/workflows/close-issues.yml @@ -18,7 +18,7 @@ jobs: ISSUE_URL: ${{ github.event.issue.html_url }} run: | gh issue close $ISSUE_URL \ - --comment "As described in the template, this is not the appropriate place for questions. Please use Stack Overflow" \ + --comment "As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)" \ --reason completed gh issue lock $ISSUE_URL --reason off_topic close_feature_request: From 818776862239a7dd97d39157ec3a202c35af122c Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 11 Oct 2023 08:19:57 -0500 Subject: [PATCH 30/88] Update close-issues.yml Remove references to GITHUB_TOKEN/MY_TOKEN --- .github/workflows/close-issues.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml index 29fcde7439..f1c177baa5 100644 --- a/.github/workflows/close-issues.yml +++ b/.github/workflows/close-issues.yml @@ -14,7 +14,6 @@ jobs: runs-on: ubuntu-latest steps: - env: - GITHUB_TOKEN: ${{ secrets.MY_TOKEN }} ISSUE_URL: ${{ github.event.issue.html_url }} run: | gh issue close $ISSUE_URL \ @@ -26,7 +25,6 @@ jobs: runs-on: ubuntu-latest steps: - env: - GITHUB_TOKEN: ${{ secrets.MY_TOKEN }} ISSUE_URL: ${{ github.event.issue.html_url }} run: | gh issue close $ISSUE_URL \ From a8e9c1b436e9a35c271d8b690eefbc0d3d18df0f Mon Sep 17 00:00:00 2001 From: sumedhrao7 Date: Wed, 18 Oct 2023 07:40:50 +0530 Subject: [PATCH 31/88] added assert statements into tests/test_requests/test_header_validation in regards to the issue #6551 --- tests/test_requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_requests.py b/tests/test_requests.py index 5d8d2cd3af..a71fe7d6b8 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1702,7 +1702,7 @@ def test_header_validation(self, httpbin): } r = requests.get(httpbin("get"), headers=valid_headers) for key in valid_headers.keys(): - valid_headers[key] == r.request.headers[key] + assert valid_headers[key] == r.request.headers[key] @pytest.mark.parametrize( "invalid_header, key", From ad761abcdd2f1b5e4fcba549676b2ea52bd325cd Mon Sep 17 00:00:00 2001 From: mayank Date: Tue, 31 Oct 2023 00:50:10 +0530 Subject: [PATCH 32/88] every chardet package maps to requests.packages.chardet.* package respectively --- src/requests/packages.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/requests/packages.py b/src/requests/packages.py index 77c45c9e90..9962bcd269 100644 --- a/src/requests/packages.py +++ b/src/requests/packages.py @@ -23,6 +23,5 @@ target = chardet.__name__ for mod in list(sys.modules): if mod == target or mod.startswith(f"{target}."): - target = target.replace(target, "chardet") - sys.modules[f"requests.packages.{target}"] = sys.modules[mod] -# Kinda cool, though, right? + sys.modules[f"requests.packages.{mod}"] = sys.modules[mod] +# Kinda cool, though, right? \ No newline at end of file From e9b1217cff710307e5de9fb8ce2fc21eb79acec3 Mon Sep 17 00:00:00 2001 From: mayank Date: Tue, 31 Oct 2023 20:37:59 +0530 Subject: [PATCH 33/88] added handling for chardet and charset_normalizer imports --- src/requests/packages.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/requests/packages.py b/src/requests/packages.py index 9962bcd269..34fccdb71d 100644 --- a/src/requests/packages.py +++ b/src/requests/packages.py @@ -24,4 +24,6 @@ for mod in list(sys.modules): if mod == target or mod.startswith(f"{target}."): sys.modules[f"requests.packages.{mod}"] = sys.modules[mod] + target = target.replace(target, "chardet") + sys.modules[f"requests.packages.{target}"] = sys.modules[mod] # Kinda cool, though, right? \ No newline at end of file From d7490c9d2dc967f68c6ca38b73aa099bc888a04e Mon Sep 17 00:00:00 2001 From: amkarn258 <55189266+amkarn258@users.noreply.github.com> Date: Tue, 31 Oct 2023 22:36:39 +0530 Subject: [PATCH 34/88] Update src/requests/packages.py Co-authored-by: Ian Stapleton Cordasco --- src/requests/packages.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/requests/packages.py b/src/requests/packages.py index 34fccdb71d..0a90f54d99 100644 --- a/src/requests/packages.py +++ b/src/requests/packages.py @@ -23,7 +23,8 @@ target = chardet.__name__ for mod in list(sys.modules): if mod == target or mod.startswith(f"{target}."): - sys.modules[f"requests.packages.{mod}"] = sys.modules[mod] - target = target.replace(target, "chardet") - sys.modules[f"requests.packages.{target}"] = sys.modules[mod] + imported_mod = sys.modules[mod] + sys.modules[f"requests.packages.{mod}"] = imported_mod + mod = mod.replace(target, "chardet") + sys.modules[f"requests.packages.{mod}"] = imported_mod # Kinda cool, though, right? \ No newline at end of file From 89cde235bec9374273281c1b4c9277c409246a6c Mon Sep 17 00:00:00 2001 From: mayank Date: Sat, 4 Nov 2023 23:20:21 +0530 Subject: [PATCH 35/88] checkstyle --- src/requests/packages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/packages.py b/src/requests/packages.py index 0a90f54d99..a9e5ae087d 100644 --- a/src/requests/packages.py +++ b/src/requests/packages.py @@ -27,4 +27,4 @@ sys.modules[f"requests.packages.{mod}"] = imported_mod mod = mod.replace(target, "chardet") sys.modules[f"requests.packages.{mod}"] = imported_mod -# Kinda cool, though, right? \ No newline at end of file +# Kinda cool, though, right? From c32b046243dcbf0dceb952da1317261109ac45c4 Mon Sep 17 00:00:00 2001 From: Matthew Carruth Date: Wed, 15 Nov 2023 17:00:28 -0800 Subject: [PATCH 36/88] Fix missing space in error message --- src/requests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/utils.py b/src/requests/utils.py index 1ae77d68ff..629ccb73d4 100644 --- a/src/requests/utils.py +++ b/src/requests/utils.py @@ -1051,7 +1051,7 @@ def _validate_header_part(header, header_part, header_validator_index): if not validator.match(header_part): header_kind = "name" if header_validator_index == 0 else "value" raise InvalidHeader( - f"Invalid leading whitespace, reserved character(s), or return" + f"Invalid leading whitespace, reserved character(s), or return " f"character(s) in header {header_kind}: {header_part!r}" ) From e66a07b28651ddeab4297fbf3a600cb42b21dfe6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:28:17 +0000 Subject: [PATCH 37/88] Bump dessant/lock-threads from 4.0.1 to 5.0.0 Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 4.0.1 to 5.0.0. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/main/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/be8aa5be94131386884a6da4189effda9b14aa21...d42e5f49803f3c4e14ffee0378e31481265dda22) --- updated-dependencies: - dependency-name: dessant/lock-threads dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lock-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock-issues.yml b/.github/workflows/lock-issues.yml index 66f68a1900..7d5a3c6525 100644 --- a/.github/workflows/lock-issues.yml +++ b/.github/workflows/lock-issues.yml @@ -13,7 +13,7 @@ jobs: if: github.repository_owner == 'psf' runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@be8aa5be94131386884a6da4189effda9b14aa21 # v4.0.1 + - uses: dessant/lock-threads@d42e5f49803f3c4e14ffee0378e31481265dda22 # v5.0.0 with: issue-lock-inactive-days: 90 pr-lock-inactive-days: 90 From 15849947ec4b8b7c3c136a47e950499edfd36921 Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Wed, 22 Nov 2023 11:31:53 +0000 Subject: [PATCH 38/88] fix docstring typo: a -> as --- src/requests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/utils.py b/src/requests/utils.py index 629ccb73d4..c3b123ea4e 100644 --- a/src/requests/utils.py +++ b/src/requests/utils.py @@ -859,7 +859,7 @@ def select_proxy(url, proxies): def resolve_proxies(request, proxies, trust_env=True): """This method takes proxy information from a request and configuration input to resolve a mapping of target proxies. This will consider settings - such a NO_PROXY to strip proxy configurations. + such as NO_PROXY to strip proxy configurations. :param request: Request or PreparedRequest :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs From f6707042d8b18d2a3737380bf58ff020872fb07b Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Mon, 27 Nov 2023 17:27:43 -0500 Subject: [PATCH 39/88] Unit test for string containing multi-byte UTF-8 There are two tests here. One demonstrating existing, correct behavior for `data=bytes`, and another, failing, test for the case where `data=string` and the string contains multi-byte UTF-8. --- tests/test_requests.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index a71fe7d6b8..b6fb84d1bd 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1808,6 +1808,23 @@ def test_autoset_header_values_are_native(self, httpbin): assert p.headers["Content-Length"] == length + def test_content_length_for_bytes_data(self, httpbin): + data = "This is a string containing multi-byte UTF-8 ☃️" + encoded_data = data.encode("utf-8") + length = str(len(encoded_data)) + req = requests.Request("POST", httpbin("post"), data=encoded_data) + p = req.prepare() + + assert p.headers["Content-Length"] == length + + def test_content_length_for_string_data_counts_bytes(self, httpbin): + data = "This is a string containing multi-byte UTF-8 ☃️" + length = str(len(data.encode("utf-8"))) + req = requests.Request("POST", httpbin("post"), data=data) + p = req.prepare() + + assert p.headers["Content-Length"] == length + def test_nonhttp_schemes_dont_check_URLs(self): test_urls = ( "data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==", From b37878d3407995e41fd3c160fd04d5d0afda1130 Mon Sep 17 00:00:00 2001 From: Ata Tuzuner Date: Tue, 28 Nov 2023 18:12:22 -0500 Subject: [PATCH 40/88] Too early definition added to 425 status code type --- src/requests/status_codes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/status_codes.py b/src/requests/status_codes.py index 4bd072be97..235881224f 100644 --- a/src/requests/status_codes.py +++ b/src/requests/status_codes.py @@ -79,7 +79,7 @@ 422: ("unprocessable_entity", "unprocessable"), 423: ("locked",), 424: ("failed_dependency", "dependency"), - 425: ("unordered_collection", "unordered"), + 425: ("unordered_collection", "unordered", "too_early"), 426: ("upgrade_required", "upgrade"), 428: ("precondition_required", "precondition"), 429: ("too_many_requests", "too_many"), From 889910c77a9618dc59dd800c17913e2b1644cee3 Mon Sep 17 00:00:00 2001 From: Ata Tuzuner Date: Wed, 29 Nov 2023 12:24:15 -0500 Subject: [PATCH 41/88] Added tests for status code 425 definitions. --- tests/test_requests.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index a71fe7d6b8..0ac3092f5e 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -2795,3 +2795,16 @@ def test_json_decode_persists_doc_attr(self, httpbin): with pytest.raises(requests.exceptions.JSONDecodeError) as excinfo: r.json() assert excinfo.value.doc == r.text + + def test_status_code_425(self): + r1 = requests.codes.get("TOO_EARLY") + r2 = requests.codes.get("too_early") + r3 = requests.codes.get("UNORDERED") + r4 = requests.codes.get("unordered") + r5 = requests.codes.get("UNORDERED_COLLECTION") + r6 = requests.codes.get("unordered_collection") + + assert r1 == 425 + assert r2 == 425 + assert r3 == 425 + assert r4 == 425 From ec84f2c539d952499e0207849dfd3f73e2c11324 Mon Sep 17 00:00:00 2001 From: Ata Tuzuner Date: Wed, 29 Nov 2023 12:27:18 -0500 Subject: [PATCH 42/88] Fixes to test --- tests/test_requests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index 0ac3092f5e..34796dc7ec 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -2808,3 +2808,5 @@ def test_status_code_425(self): assert r2 == 425 assert r3 == 425 assert r4 == 425 + assert r5 == 425 + assert r6 == 425 From 3fd309a5c14e4cfbd96bea6c8e71b4958fe090bb Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Tue, 28 Nov 2023 13:17:49 -0500 Subject: [PATCH 43/88] Enhance `super_len` to count encoded bytes for str This fixes issue #6586 --- src/requests/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/requests/utils.py b/src/requests/utils.py index c3b123ea4e..a603a8638c 100644 --- a/src/requests/utils.py +++ b/src/requests/utils.py @@ -134,6 +134,9 @@ def super_len(o): total_length = None current_position = 0 + if isinstance(o, str): + o = o.encode("utf-8") + if hasattr(o, "__len__"): total_length = len(o) From d6ffd868ee3730f4e5c7d1595da37e2027a93eb8 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Fri, 1 Dec 2023 08:05:59 -0600 Subject: [PATCH 44/88] Update close-issues.yml I noticed the auto-labeling was working but not the auto-closing. Looking at recent actions runs I see that we need to specify the token even if we're not giving our own special token. See https://github.com/psf/requests/actions/runs/7057701782/job/19211845073#step:2:13 for additional context, namely ``` gh: To use GitHub CLI in a GitHub Actions workflow, set the GH_TOKEN environment variable. Example: env: GH_TOKEN: ${{ github.token }} ``` --- .github/workflows/close-issues.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml index f1c177baa5..bedc75ea5b 100644 --- a/.github/workflows/close-issues.yml +++ b/.github/workflows/close-issues.yml @@ -15,6 +15,7 @@ jobs: steps: - env: ISSUE_URL: ${{ github.event.issue.html_url }} + GH_TOKEN: ${{ github.token }} run: | gh issue close $ISSUE_URL \ --comment "As described in the template, we won't be able to answer questions on this issue tracker. Please use [Stack Overflow](https://stackoverflow.com/)" \ @@ -26,6 +27,7 @@ jobs: steps: - env: ISSUE_URL: ${{ github.event.issue.html_url }} + GH_TOKEN: ${{ github.token }} run: | gh issue close $ISSUE_URL \ --comment "As described in the template, Requests is not accepting feature requests" \ From ba67dc8dccd114faf8347e66c56baaa9d72f6429 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:07:15 +0000 Subject: [PATCH 45/88] Bump actions/setup-python from 4.7.0 to 5.0.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.7.0 to 5.0.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/61a6322f88396a6271a6ee3565807d608ecaddd1...0a5c61591373683505ea898e09a3ea4f39ef2b9c) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3a358a290a..b35a32d13a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: Set up Python - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 with: python-version: "3.x" - name: Run pre-commit diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 5461ccddfb..8178ed423a 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 with: python-version: ${{ matrix.python-version }} cache: 'pip' From a64f32ba453bc19aa679018838bee8ef8cc9a68b Mon Sep 17 00:00:00 2001 From: Rodrigo Silva Date: Wed, 13 Dec 2023 10:05:12 -0300 Subject: [PATCH 46/88] Add note on connection timeout being larger than specified. Fix #5773 On servers with multiple IPs, such as IPv4 and IPv6, `urllib3` tries each address sequentially until one successfully connects, using the specified timeout for _each_ attempt, leading to a total connection timeout that is a _multiple_ of the requested time. --- docs/user/advanced.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index c90a13dc6d..129cf4d0d6 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -1122,4 +1122,12 @@ coffee. r = requests.get('https://github.com', timeout=None) +.. note:: The connect timeout applies to each connection attempt to an IP address. +If multiple addresses exist for a domain name, the underlying ``urllib3`` will +try each address sequentially until one successfully connects. +This may lead to an effective total connection timeout *multiple* times longer +than the specified time, e.g. an unresponsive server having both IPv4 and IPv6 +addresses will have its perceived timeout *doubled*, so take that into account +when setting the connection timeout. + .. _`connect()`: https://linux.die.net/man/2/connect From c7c2ebf1a7b4b0f4149b3935b781e1392015e2d6 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Fri, 15 Dec 2023 20:59:51 +0000 Subject: [PATCH 47/88] Add now mandatory readthedocs config file Docs builds currently fail with: ``` Problem in your project's configuration. No default configuration file found at repository's root. See https://docs.readthedocs.io/en/stable/config-file/ ``` See e.g. https://readthedocs.org/projects/requests/builds/22842479/ --- .readthedocs.yaml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000000..dd3fb9d3ba --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,28 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +formats: + - pdf + - epub + +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - path: . + - requirements: docs/requirements.txt From 951dd15fa619b23aba6b72532f1aac30b69389b7 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Sat, 16 Dec 2023 07:26:23 -0600 Subject: [PATCH 48/88] Update docs/user/advanced.rst fix indentation for note so it renders properly --- docs/user/advanced.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 129cf4d0d6..3f5243ee24 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -1123,11 +1123,11 @@ coffee. r = requests.get('https://github.com', timeout=None) .. note:: The connect timeout applies to each connection attempt to an IP address. -If multiple addresses exist for a domain name, the underlying ``urllib3`` will -try each address sequentially until one successfully connects. -This may lead to an effective total connection timeout *multiple* times longer -than the specified time, e.g. an unresponsive server having both IPv4 and IPv6 -addresses will have its perceived timeout *doubled*, so take that into account -when setting the connection timeout. + If multiple addresses exist for a domain name, the underlying ``urllib3`` will + try each address sequentially until one successfully connects. + This may lead to an effective total connection timeout *multiple* times longer + than the specified time, e.g. an unresponsive server having both IPv4 and IPv6 + addresses will have its perceived timeout *doubled*, so take that into account + when setting the connection timeout. .. _`connect()`: https://linux.die.net/man/2/connect From 92f9e431c99d5e0776a00c10a90dfdf11cd45ba0 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Sat, 16 Dec 2023 07:29:50 -0600 Subject: [PATCH 49/88] Update docs/user/advanced.rst Add note about wall clock too --- docs/user/advanced.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 3f5243ee24..5e5e36f302 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -1129,5 +1129,11 @@ coffee. than the specified time, e.g. an unresponsive server having both IPv4 and IPv6 addresses will have its perceived timeout *doubled*, so take that into account when setting the connection timeout. +.. note:: Neither the connect nor read timeouts are `wall clock`_. This means + that if you start a request, and look at the time, and then look at + the time when the request finishes or times out, the real-world time + may be greater than what you specified. + +.. _`wall clock`: https://wiki.php.net/rfc/max_execution_wall_time .. _`connect()`: https://linux.die.net/man/2/connect From 1447bccc057e7fbffdfecd75cd4922702489a14b Mon Sep 17 00:00:00 2001 From: Jaikish Pai Date: Sun, 17 Dec 2023 22:34:30 +0100 Subject: [PATCH 50/88] fix for ##6604 --- docs/_templates/sidebarintro.html | 10 +++++----- docs/_templates/sidebarlogo.html | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html index 2b595b54d4..6a2fcea33e 100644 --- a/docs/_templates/sidebarintro.html +++ b/docs/_templates/sidebarintro.html @@ -16,11 +16,11 @@

Useful Links

    -
  • Quickstart
  • -
  • Advanced Usage
  • -
  • API Reference
  • -
  • Release History
  • -
  • Contributors Guide
  • +
  • Quickstart
  • +
  • Advanced Usage
  • +
  • API Reference
  • +
  • Release History
  • +
  • Contributors Guide
  • diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html index a3454b7c49..d0d14ce85b 100644 --- a/docs/_templates/sidebarlogo.html +++ b/docs/_templates/sidebarlogo.html @@ -11,15 +11,15 @@

    Useful Links

      -
    • Quickstart
    • -
    • Advanced Usage
    • -
    • API Reference
    • -
    • Release History
    • -
    • Contributors Guide
    • +
    • Quickstart
    • +
    • Advanced Usage
    • +
    • API Reference
    • +
    • Release History
    • +
    • Contributors Guide
    • -
    • Recommended Packages and Extensions
    • +
    • Recommended Packages and Extensions
    • From 421b1f175766065e2feb569990c528df16c2874f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 16:39:47 +0000 Subject: [PATCH 51/88] Bump github/codeql-action from 2.22.1 to 3.22.11 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.1 to 3.22.11. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/fdcae64e1484d349b3366718cdfef3d404390e85...b374143c1149a9115d881581d29b8390bbcbb59c) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a2a43cfcde..4f0eebf29e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 + uses: github/codeql-action/init@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 + uses: github/codeql-action/autobuild@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 + uses: github/codeql-action/analyze@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11 From 242d3113c09d10ba9a11dbcc05e0310a1e7568af Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Sat, 23 Dec 2023 16:16:50 +0000 Subject: [PATCH 52/88] docs: specify sphinx dirhtml builder With the requirement of a configuration file, the default builder of `dirhtml` that RTD used to use is no longer specified. This leads to URLs ending in `.html` now, which breaks other exisitng references. Refs: #6603 Refs: https://docs.readthedocs.io/en/stable/config-file/v2.html#sphinx-builder Refs: https://www.sphinx-doc.org/en/master/usage/builders/index.html#sphinx.builders.dirhtml.DirectoryHTMLBuilder Signed-off-by: Mike Fiedler --- .readthedocs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index dd3fb9d3ba..0e2c719e08 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -13,6 +13,7 @@ build: # Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/conf.py + builder: "dirhtml" # Optionally build your docs in additional formats such as PDF and ePub formats: From b5bd0f14cc6fe12a712d21d7881aab59d0dd9951 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Sat, 23 Dec 2023 17:17:34 +0000 Subject: [PATCH 53/88] docs: add label to socks heading When trying to link via intersphinx, a label must be used. Otherwise a full URL is required, which is less desirable. Signed-off-by: Mike Fiedler --- docs/user/advanced.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 5e5e36f302..ecd17cb300 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -666,6 +666,8 @@ You override this default certificate bundle by setting the ``REQUESTS_CA_BUNDLE >>> import requests >>> requests.get('https://example.org') +.. _socks: + SOCKS ^^^^^ From f23346a9b8e74de01220cce96c037bbd2404a1c6 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Sat, 23 Dec 2023 17:36:34 +0000 Subject: [PATCH 54/88] Revert "Merge pull request #6605 from jaikishpai/fix-#6604" This reverts commit 1396eb6f7a1116d49f1f0df0ddf895343f84af64, reversing changes made to e4c821a24778c3a33beec2aa86f3d58e3d94b58c. --- docs/_templates/sidebarintro.html | 10 +++++----- docs/_templates/sidebarlogo.html | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html index 6a2fcea33e..2b595b54d4 100644 --- a/docs/_templates/sidebarintro.html +++ b/docs/_templates/sidebarintro.html @@ -16,11 +16,11 @@

      Useful Links

        -
      • Quickstart
      • -
      • Advanced Usage
      • -
      • API Reference
      • -
      • Release History
      • -
      • Contributors Guide
      • +
      • Quickstart
      • +
      • Advanced Usage
      • +
      • API Reference
      • +
      • Release History
      • +
      • Contributors Guide
      • diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html index d0d14ce85b..a3454b7c49 100644 --- a/docs/_templates/sidebarlogo.html +++ b/docs/_templates/sidebarlogo.html @@ -11,15 +11,15 @@

        Useful Links

          -
        • Quickstart
        • -
        • Advanced Usage
        • -
        • API Reference
        • -
        • Release History
        • -
        • Contributors Guide
        • +
        • Quickstart
        • +
        • Advanced Usage
        • +
        • API Reference
        • +
        • Release History
        • +
        • Contributors Guide
        • -
        • Recommended Packages and Extensions
        • +
        • Recommended Packages and Extensions
        • From bfba9dc68c841b78ca51e6302d3283d33167f773 Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Sat, 23 Dec 2023 18:09:08 +0000 Subject: [PATCH 55/88] docs: replace concrete URLs with references Any development links will now refer back to the generated docs. Signed-off-by: Mike Fiedler --- docs/_templates/sidebarintro.html | 12 ++++++------ docs/_templates/sidebarlogo.html | 12 ++++++------ docs/community/faq.rst | 2 +- docs/user/quickstart.rst | 2 ++ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html index 2b595b54d4..607bf92c4e 100644 --- a/docs/_templates/sidebarintro.html +++ b/docs/_templates/sidebarintro.html @@ -16,15 +16,15 @@

          Useful Links

            -
          • Quickstart
          • -
          • Advanced Usage
          • -
          • API Reference
          • -
          • Release History
          • -
          • Contributors Guide
          • +
          • Quickstart
          • +
          • Advanced Usage
          • +
          • API Reference
          • +
          • Release History
          • +
          • Contributors Guide
          • -
          • Recommended Packages and Extensions
          • +
          • Recommended Packages and Extensions
          • diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html index a3454b7c49..71eb82e726 100644 --- a/docs/_templates/sidebarlogo.html +++ b/docs/_templates/sidebarlogo.html @@ -11,15 +11,15 @@

            Useful Links

              -
            • Quickstart
            • -
            • Advanced Usage
            • -
            • API Reference
            • -
            • Release History
            • -
            • Contributors Guide
            • +
            • Quickstart
            • +
            • Advanced Usage
            • +
            • API Reference
            • +
            • Release History
            • +
            • Contributors Guide
            • -
            • Recommended Packages and Extensions
            • +
            • Recommended Packages and Extensions
            • diff --git a/docs/community/faq.rst b/docs/community/faq.rst index 9d900be2b5..33fb7e84f3 100644 --- a/docs/community/faq.rst +++ b/docs/community/faq.rst @@ -22,7 +22,7 @@ Custom User-Agents? ------------------- Requests allows you to easily override User-Agent strings, along with -any other HTTP Header. See `documentation about headers `_. +any other HTTP Header. See :ref:`documentation about headers `. diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst index 464e4f5fa5..bbf3745eea 100644 --- a/docs/user/quickstart.rst +++ b/docs/user/quickstart.rst @@ -201,6 +201,8 @@ may better fit your use cases. were returned, use ``Response.raw``. +.. _custom-headers: + Custom Headers -------------- From 25939d8784dc8bec784b8129152efa4443daa82f Mon Sep 17 00:00:00 2001 From: Mike Fiedler Date: Sat, 23 Dec 2023 18:15:33 +0000 Subject: [PATCH 56/88] add myself Signed-off-by: Mike Fiedler --- AUTHORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index c4e554d478..1dc04117cf 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -192,3 +192,4 @@ Patches and Suggestions - Alessio Izzo (`@aless10 `_) - Sylvain Marié (`@smarie `_) - Hod Bin Noon (`@hodbn `_) +- Mike Fiedler (`@miketheman `_) From b0e6c9bf85378acd079ca84a4481f361b47a2147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:01:37 +0000 Subject: [PATCH 57/88] Bump github/codeql-action from 3.22.11 to 3.23.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.22.11 to 3.23.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b374143c1149a9115d881581d29b8390bbcbb59c...e5f05b81d5b6ff8cfa111c80c22c5fd02a384118) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4f0eebf29e..c03a8a7ca8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11 + uses: github/codeql-action/init@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11 + uses: github/codeql-action/autobuild@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11 + uses: github/codeql-action/analyze@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 From 3ff3ff21dd45957c9e143cd500291959bb15f690 Mon Sep 17 00:00:00 2001 From: Thomas Dehghani Date: Wed, 31 Jan 2024 17:07:35 +0100 Subject: [PATCH 58/88] Fix #6628 - JSONDecodeError are not deserializable requests.exceptions.JSONDecodeError are not deserializable: calling `pickle.dumps` followed by `pickle.loads` will trigger an error. This is particularly a problem in a process pool, as an attempt to decode json on an invalid json document will result in the entire process pool crashing. This is due to the MRO of the `requests.exceptions.JSONDecodeError` class: the `__reduce__` method called when pickling an instance is not the one from the JSON library parent: two out of three args expected for instantiation will be dropped, and the instance can't be deserialised. By specifying in the class which parent `__reduce__` method should be called, the bug is fixed as all args are carried over in the resulting pickled bytes. --- src/requests/exceptions.py | 10 ++++++++++ tests/test_requests.py | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/requests/exceptions.py b/src/requests/exceptions.py index e1cedf883d..83986b4898 100644 --- a/src/requests/exceptions.py +++ b/src/requests/exceptions.py @@ -41,6 +41,16 @@ def __init__(self, *args, **kwargs): CompatJSONDecodeError.__init__(self, *args) InvalidJSONError.__init__(self, *self.args, **kwargs) + def __reduce__(self): + """ + The __reduce__ method called when pickling the object must + be the one from the JSONDecodeError (be it json/simplejson) + as it expects all the arguments for instantiation, not just + one like the IOError, and the MRO would by default call the + __reduce__ method from the IOError due to the inheritance order. + """ + return CompatJSONDecodeError.__reduce__(self) + class HTTPError(RequestException): """An HTTP error occurred.""" diff --git a/tests/test_requests.py b/tests/test_requests.py index 34796dc7ec..77aac3fecb 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -2810,3 +2810,13 @@ def test_status_code_425(self): assert r4 == 425 assert r5 == 425 assert r6 == 425 + + +def test_json_decode_errors_are_serializable_deserializable(): + json_decode_error = requests.exceptions.JSONDecodeError( + "Extra data", + '{"responseCode":["706"],"data":null}{"responseCode":["706"],"data":null}', + 36, + ) + deserialized_error = pickle.loads(pickle.dumps(json_decode_error)) + assert repr(json_decode_error) == repr(deserialized_error) From a5a0e4b587c7f2de4250ec965caf21b8fca172e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:38:01 +0000 Subject: [PATCH 59/88] Bump github/codeql-action from 3.23.0 to 3.24.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.23.0 to 3.24.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e5f05b81d5b6ff8cfa111c80c22c5fd02a384118...e8893c57a1f3a2b659b6b55564fdfdbbd2982911) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c03a8a7ca8..26a4348a4b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 + uses: github/codeql-action/init@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 + uses: github/codeql-action/autobuild@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # v3.23.0 + uses: github/codeql-action/analyze@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 From 6106a63eb6c0fa490efa73d44388ac25b1b08af4 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 20 Feb 2024 11:58:35 -0800 Subject: [PATCH 60/88] Cleanup defunct links from community docs page --- docs/community/out-there.rst | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/community/out-there.rst b/docs/community/out-there.rst index c33ab3c95b..c75c71f6a2 100644 --- a/docs/community/out-there.rst +++ b/docs/community/out-there.rst @@ -1,22 +1,10 @@ Integrations ============ -Python for iOS --------------- - -Requests is built into the wonderful `Python for iOS `_ runtime! - -To give it a try, simply:: - - import requests - - Articles & Talks ================ -- `Python for the Web `_ teaches how to use Python to interact with the web, using Requests. - `Daniel Greenfeld's Review of Requests `_ -- `My 'Python for Humans' talk `_ ( `audio `_ ) -- `Issac Kelly's 'Consuming Web APIs' talk `_ +- `Issac Kelly's 'Consuming Web APIs' talk `_ - `Blog post about Requests via Yum `_ - `Russian blog post introducing Requests `_ - `Sending JSON in Requests `_ From 5fc10bf1f5185f330f8471c738ce753b3e231008 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 20 Feb 2024 13:37:25 -0800 Subject: [PATCH 61/88] Fix httpbin pin for test suite --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index f137c46a33..a663015cda 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ pytest>=2.8.0,<=6.2.5 pytest-cov pytest-httpbin==2.0.0 -httpbin==0.10.0 +httpbin~=0.10.0 trustme wheel cryptography<40.0.0; python_version <= '3.7' and platform_python_implementation == 'PyPy' From 28855fd43a68bf26fec23aa9b548239e13255edf Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 20 Feb 2024 13:58:26 -0800 Subject: [PATCH 62/88] Update supported copies of PyPy Dropped support for pypy-3.7 and pypy-3.8 which are no longer maintained by upstream. Added support for pypy-3.10. --- .github/workflows/run-tests.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 8178ed423a..24981a3b58 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -12,13 +12,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev", "pypy-3.8", "pypy-3.9"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev", "pypy-3.9", "pypy-3.10"] os: [ubuntu-22.04, macOS-latest, windows-latest] - include: - # pypy-3.7 on Windows and Mac OS currently fails trying to compile - # cryptography. Moving pypy-3.7 to only test linux. - - python-version: pypy-3.7 - os: ubuntu-latest steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 From 8fa4302322f1a34053683b7f4c0d2ee5ef0ebd64 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 20 Feb 2024 15:04:04 -0800 Subject: [PATCH 63/88] Update Sphinx to work with latest readthedocs requirements --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 8c2488252b..2af334d57b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,3 @@ # Pinning to avoid unexpected breakages. # Used by RTD to generate docs. -Sphinx==4.2.0 +Sphinx==7.2.6 From 58cea7a7282999adafdc19a4e82e2d09207ab568 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 20 Feb 2024 15:22:20 -0800 Subject: [PATCH 64/88] Drop support for CPython 3.7 --- .github/workflows/run-tests.yml | 2 +- README.md | 2 +- docs/community/faq.rst | 2 +- docs/index.rst | 2 +- requirements-dev.txt | 1 - setup.py | 7 +++---- tox.ini | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 24981a3b58..3275080233 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev", "pypy-3.9", "pypy-3.10"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.9", "pypy-3.10"] os: [ubuntu-22.04, macOS-latest, windows-latest] steps: diff --git a/README.md b/README.md index c4b170e70f..79cf54d1e1 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Requests is available on PyPI: $ python -m pip install requests ``` -Requests officially supports Python 3.7+. +Requests officially supports Python 3.8+. ## Supported Features & Best–Practices diff --git a/docs/community/faq.rst b/docs/community/faq.rst index 33fb7e84f3..b6ea654e60 100644 --- a/docs/community/faq.rst +++ b/docs/community/faq.rst @@ -55,7 +55,7 @@ Chris Adams gave an excellent summary on Python 3 Support? ----------------- -Yes! Requests officially supports Python 3.7+ and PyPy. +Yes! Requests officially supports Python 3.8+ and PyPy. Python 2 Support? ----------------- diff --git a/docs/index.rst b/docs/index.rst index 50b0adc3d2..289250c2a4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -72,7 +72,7 @@ Requests is ready for today's web. - Chunked Requests - ``.netrc`` Support -Requests officially supports Python 3.7+, and runs great on PyPy. +Requests officially supports Python 3.8+, and runs great on PyPy. The User Guide diff --git a/requirements-dev.txt b/requirements-dev.txt index a663015cda..13173f3ae5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,4 +5,3 @@ pytest-httpbin==2.0.0 httpbin~=0.10.0 trustme wheel -cryptography<40.0.0; python_version <= '3.7' and platform_python_implementation == 'PyPy' diff --git a/setup.py b/setup.py index dc8043a695..1b0eb377b4 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from setuptools.command.test import test as TestCommand CURRENT_PYTHON = sys.version_info[:2] -REQUIRED_PYTHON = (3, 7) +REQUIRED_PYTHON = (3, 8) if CURRENT_PYTHON < REQUIRED_PYTHON: sys.stderr.write( @@ -20,7 +20,7 @@ consider upgrading to a supported Python version. If you can't upgrade your Python version, you'll need to -pin to an older version of Requests (<2.28). +pin to an older version of Requests (<2.32.0). """.format( *(REQUIRED_PYTHON + CURRENT_PYTHON) ) @@ -94,7 +94,7 @@ def run_tests(self): package_data={"": ["LICENSE", "NOTICE"]}, package_dir={"": "src"}, include_package_data=True, - python_requires=">=3.7", + python_requires=">=3.8", install_requires=requires, license=about["__license__"], zip_safe=False, @@ -107,7 +107,6 @@ def run_tests(self): "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/tox.ini b/tox.ini index 92ab6d1a24..d2b529e2b9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{37,38,39,310,311,312}-{default, use_chardet_on_py3} +envlist = py{38,39,310,311,312}-{default, use_chardet_on_py3} [testenv] deps = -rrequirements-dev.txt From 60389df6d69ce833164696dcf36cbb43336d3426 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 21 Feb 2024 19:09:48 -0600 Subject: [PATCH 65/88] Trim excess leading path separators A URL with excess leading / (path-separator)s would cause urllib3 to attempt to reparse the request-uri as a full URI with a host and port. This bypasses that logic in ConnectionPool.urlopen by replacing these leading /s with just a single /. Closes #6643 --- src/requests/adapters.py | 3 +++ tests/test_adapters.py | 8 ++++++++ 2 files changed, 11 insertions(+) create mode 100644 tests/test_adapters.py diff --git a/src/requests/adapters.py b/src/requests/adapters.py index eb240fa954..fc5606bdcb 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -390,6 +390,9 @@ def request_url(self, request, proxies): using_socks_proxy = proxy_scheme.startswith("socks") url = request.path_url + if url.startswith("//"): # Don't confuse urllib3 + url = f"/{url.lstrip('/')}" + if is_proxied_http_request and not using_socks_proxy: url = urldefragauth(request.url) diff --git a/tests/test_adapters.py b/tests/test_adapters.py new file mode 100644 index 0000000000..6c55d5a130 --- /dev/null +++ b/tests/test_adapters.py @@ -0,0 +1,8 @@ +import requests.adapters + + +def test_request_url_trims_leading_path_separators(): + """See also https://github.com/psf/requests/issues/6643.""" + a = requests.adapters.HTTPAdapter() + p = requests.Request(method="GET", url="http://127.0.0.1:10000//v:h").prepare() + assert "/v:h" == a.request_url(p, {}) From 0ec2780c291107b6686996e4b38f3d63e076eda7 Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Fri, 24 Nov 2023 10:37:33 +0000 Subject: [PATCH 66/88] update broken github pagination link --- docs/user/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index ecd17cb300..a61aa85074 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -948,7 +948,7 @@ Link Headers Many HTTP APIs feature Link headers. They make APIs more self describing and discoverable. -GitHub uses these for `pagination `_ +GitHub uses these for `pagination `_ in their API, for example:: >>> url = 'https://api.github.com/users/kennethreitz/repos?page=1&per_page=10' From d3b3399ece1f76387d323983638e0838c06e88ea Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Fri, 24 Nov 2023 10:44:09 +0000 Subject: [PATCH 67/88] update authors github link Update account link for original author which has changed. --- AUTHORS.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 1dc04117cf..6e017c9a91 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -8,7 +8,7 @@ Keepers of the Crystals Previous Keepers of Crystals ```````````````````````````` -- Kenneth Reitz `@ken-reitz `_, reluctant Keeper of the Master Crystal. +- Kenneth Reitz `@kennethreitz `_, reluctant Keeper of the Master Crystal. - Cory Benfield `@lukasa `_ - Ian Cordasco `@sigmavirus24 `_. From 541aa80ca3d0ee771611bd155a5172efaa26d9da Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Fri, 24 Nov 2023 11:04:16 +0000 Subject: [PATCH 68/88] update urllib3 docs link --- docs/user/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index a61aa85074..037e50a4fc 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -291,7 +291,7 @@ versions of Requests. For the sake of security we recommend upgrading certifi frequently! .. _HTTP persistent connection: https://en.wikipedia.org/wiki/HTTP_persistent_connection -.. _connection pooling: https://urllib3.readthedocs.io/en/latest/reference/index.html#module-urllib3.connectionpool +.. _connection pooling: https://urllib3.readthedocs.io/en/latest/reference/urllib3.connectionpool.html .. _certifi: https://certifiio.readthedocs.io/ .. _Mozilla trust store: https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt From 5f1c3c22ff7c7bb89a4e017e3f336cbc88e189c3 Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Fri, 24 Nov 2023 11:04:32 +0000 Subject: [PATCH 69/88] remove section with broken link to survey --- docs/user/quickstart.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst index bbf3745eea..33c2732c7f 100644 --- a/docs/user/quickstart.rst +++ b/docs/user/quickstart.rst @@ -568,6 +568,3 @@ All exceptions that Requests explicitly raises inherit from ----------------------- Ready for more? Check out the :ref:`advanced ` section. - - -If you're on the job market, consider taking `this programming quiz `_. A substantial donation will be made to this project, if you find a job through this platform. From 0a7f662aa70d39b6c3b5c804be00af5731292550 Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Fri, 24 Nov 2023 11:04:54 +0000 Subject: [PATCH 70/88] Make example URL format a literal rather than an actual link The rendered docs 'auto-link' this, which might encourage users to click the link, even though it doesn't go anywhere. --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index bbe6dd425b..432ee3b174 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -14,7 +14,7 @@ dev forwarding of `Proxy-Authorization` headers to destination servers when following HTTPS redirects. - When proxies are defined with user info (https://user:pass@proxy:8080), Requests + When proxies are defined with user info (`https://user:pass@proxy:8080`), Requests will construct a `Proxy-Authorization` header that is attached to the request to authenticate with the proxy. From a0e79bad059f2d0e6d3c00a2a7311acb2bef4d67 Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Fri, 24 Nov 2023 11:05:45 +0000 Subject: [PATCH 71/88] update broken rfc link ietf seems appropriate here - it's used elsewhere in the requets docs in several places. --- docs/user/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 037e50a4fc..ff3a3d0f26 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -1099,7 +1099,7 @@ The **connect** timeout is the number of seconds Requests will wait for your client to establish a connection to a remote machine (corresponding to the `connect()`_) call on the socket. It's a good practice to set connect timeouts to slightly larger than a multiple of 3, which is the default `TCP packet -retransmission window `_. +retransmission window `_. Once your client has connected to the server and sent the HTTP request, the **read** timeout is the number of seconds the client will wait for the server From c0813a2d910ea6b4f8438b91d315b8d181302356 Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Sun, 3 Mar 2024 07:00:49 -0600 Subject: [PATCH 72/88] Use TLS settings in selecting connection pool Previously, if someone made a request with `verify=False` then made a request where they expected verification to be enabled to the same host, they would potentially reuse a connection where TLS had not been verified. This fixes that issue. --- src/requests/adapters.py | 58 +++++++++++++++++++++++++++++++++++++++- tests/test_requests.py | 7 +++++ tox.ini | 2 +- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/requests/adapters.py b/src/requests/adapters.py index fc5606bdcb..6c62766639 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -8,6 +8,7 @@ import os.path import socket # noqa: F401 +import typing from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError from urllib3.exceptions import HTTPError as _HTTPError @@ -61,12 +62,38 @@ def SOCKSProxyManager(*args, **kwargs): raise InvalidSchema("Missing dependencies for SOCKS support.") +if typing.TYPE_CHECKING: + from .models import PreparedRequest + + DEFAULT_POOLBLOCK = False DEFAULT_POOLSIZE = 10 DEFAULT_RETRIES = 0 DEFAULT_POOL_TIMEOUT = None +def _urllib3_request_context( + request: "PreparedRequest", verify: "bool | str | None" +) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])": + host_params = {} + pool_kwargs = {} + parsed_request_url = urlparse(request.url) + scheme = parsed_request_url.scheme.lower() + port = parsed_request_url.port + cert_reqs = "CERT_REQUIRED" + if verify is False: + cert_reqs = "CERT_NONE" + if isinstance(verify, str): + pool_kwargs["ca_certs"] = verify + pool_kwargs["cert_reqs"] = cert_reqs + host_params = { + "scheme": scheme, + "host": parsed_request_url.hostname, + "port": port, + } + return host_params, pool_kwargs + + class BaseAdapter: """The Base Transport Adapter""" @@ -327,6 +354,35 @@ def build_response(self, req, resp): return response + def _get_connection(self, request, verify, proxies=None): + # Replace the existing get_connection without breaking things and + # ensure that TLS settings are considered when we interact with + # urllib3 HTTP Pools + proxy = select_proxy(request.url, proxies) + try: + host_params, pool_kwargs = _urllib3_request_context(request, verify) + except ValueError as e: + raise InvalidURL(e, request=request) + if proxy: + proxy = prepend_scheme_if_needed(proxy, "http") + proxy_url = parse_url(proxy) + if not proxy_url.host: + raise InvalidProxyURL( + "Please check proxy URL. It is malformed " + "and could be missing the host." + ) + proxy_manager = self.proxy_manager_for(proxy) + conn = proxy_manager.connection_from_host( + **host_params, pool_kwargs=pool_kwargs + ) + else: + # Only scheme should be lower case + conn = self.poolmanager.connection_from_host( + **host_params, pool_kwargs=pool_kwargs + ) + + return conn + def get_connection(self, url, proxies=None): """Returns a urllib3 connection for the given URL. This should not be called from user code, and is only exposed for use when subclassing the @@ -453,7 +509,7 @@ def send( """ try: - conn = self.get_connection(request.url, proxies) + conn = self._get_connection(request, verify, proxies) except LocationValueError as e: raise InvalidURL(e, request=request) diff --git a/tests/test_requests.py b/tests/test_requests.py index 32b5e6700c..d5cc13c79f 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -2828,6 +2828,13 @@ def test_status_code_425(self): assert r5 == 425 assert r6 == 425 + def test_different_connection_pool_for_tls_settings(self): + s = requests.Session() + r1 = s.get("https://invalid.badssl.com", verify=False) + assert r1.status_code == 421 + with pytest.raises(requests.exceptions.SSLError): + s.get("https://invalid.badssl.com") + def test_json_decode_errors_are_serializable_deserializable(): json_decode_error = requests.exceptions.JSONDecodeError( diff --git a/tox.ini b/tox.ini index d2b529e2b9..c438ef316a 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,7 @@ extras = security socks commands = - pytest tests + pytest {posargs:tests} [testenv:default] From a94e9b5308ffcc3d2913ab873e9810a6601a67da Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 13 Mar 2024 15:58:45 -0500 Subject: [PATCH 73/88] Add local TLS server This also adds certificates for testing purposes and files to make it easy to generate/regenerate them. This also replaces an existing test of how we utilize our pool manager such that we don't connect to badssl.com Finally, this adds additional context parameters for our pool manager to account for mTLS certificates used by clients to authenticate to a server. --- src/requests/adapters.py | 18 +++- tests/certs/README.md | 10 ++ tests/certs/expired/Makefile | 13 +++ tests/certs/expired/README.md | 11 ++ tests/certs/expired/ca/Makefile | 13 +++ tests/certs/expired/ca/ca-private.key | 28 ++++++ tests/certs/expired/ca/ca.cnf | 12 +++ tests/certs/expired/ca/ca.crt | 20 ++++ tests/certs/expired/ca/ca.srl | 1 + tests/certs/expired/server/Makefile | 16 +++ tests/certs/expired/server/cert.cnf | 24 +++++ tests/certs/expired/server/server.csr | 19 ++++ tests/certs/expired/server/server.key | 28 ++++++ tests/certs/expired/server/server.pem | 41 ++++++++ tests/certs/mtls/Makefile | 7 ++ tests/certs/mtls/README.md | 4 + tests/certs/mtls/client/Makefile | 16 +++ tests/certs/mtls/client/ca | 1 + tests/certs/mtls/client/cert.cnf | 26 +++++ tests/certs/mtls/client/client.csr | 24 +++++ tests/certs/mtls/client/client.key | 28 ++++++ tests/certs/mtls/client/client.pem | 41 ++++++++ tests/certs/valid/ca | 1 + tests/certs/valid/server/Makefile | 16 +++ tests/certs/valid/server/cert.cnf | 31 ++++++ tests/certs/valid/server/server.csr | 19 ++++ tests/certs/valid/server/server.key | 28 ++++++ tests/certs/valid/server/server.pem | 47 +++++++++ tests/test_requests.py | 140 +++++++++++++++++++++++++- tests/testserver/server.py | 42 ++++++++ 30 files changed, 716 insertions(+), 9 deletions(-) create mode 100644 tests/certs/README.md create mode 100644 tests/certs/expired/Makefile create mode 100644 tests/certs/expired/README.md create mode 100644 tests/certs/expired/ca/Makefile create mode 100644 tests/certs/expired/ca/ca-private.key create mode 100644 tests/certs/expired/ca/ca.cnf create mode 100644 tests/certs/expired/ca/ca.crt create mode 100644 tests/certs/expired/ca/ca.srl create mode 100644 tests/certs/expired/server/Makefile create mode 100644 tests/certs/expired/server/cert.cnf create mode 100644 tests/certs/expired/server/server.csr create mode 100644 tests/certs/expired/server/server.key create mode 100644 tests/certs/expired/server/server.pem create mode 100644 tests/certs/mtls/Makefile create mode 100644 tests/certs/mtls/README.md create mode 100644 tests/certs/mtls/client/Makefile create mode 120000 tests/certs/mtls/client/ca create mode 100644 tests/certs/mtls/client/cert.cnf create mode 100644 tests/certs/mtls/client/client.csr create mode 100644 tests/certs/mtls/client/client.key create mode 100644 tests/certs/mtls/client/client.pem create mode 120000 tests/certs/valid/ca create mode 100644 tests/certs/valid/server/Makefile create mode 100644 tests/certs/valid/server/cert.cnf create mode 100644 tests/certs/valid/server/server.csr create mode 100644 tests/certs/valid/server/server.key create mode 100644 tests/certs/valid/server/server.pem diff --git a/src/requests/adapters.py b/src/requests/adapters.py index 6c62766639..84ec48fc70 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -73,7 +73,9 @@ def SOCKSProxyManager(*args, **kwargs): def _urllib3_request_context( - request: "PreparedRequest", verify: "bool | str | None" + request: "PreparedRequest", + verify: "bool | str | None", + client_cert: "typing.Tuple[str, str] | str | None", ) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])": host_params = {} pool_kwargs = {} @@ -86,6 +88,14 @@ def _urllib3_request_context( if isinstance(verify, str): pool_kwargs["ca_certs"] = verify pool_kwargs["cert_reqs"] = cert_reqs + if client_cert is not None: + if isinstance(client_cert, tuple) and len(client_cert) == 2: + pool_kwargs["cert_file"] = client_cert[0] + pool_kwargs["key_file"] = client_cert[1] + else: + # According to our docs, we allow users to specify just the client + # cert path + pool_kwargs["cert_file"] = client_cert host_params = { "scheme": scheme, "host": parsed_request_url.hostname, @@ -354,13 +364,13 @@ def build_response(self, req, resp): return response - def _get_connection(self, request, verify, proxies=None): + def _get_connection(self, request, verify, proxies=None, cert=None): # Replace the existing get_connection without breaking things and # ensure that TLS settings are considered when we interact with # urllib3 HTTP Pools proxy = select_proxy(request.url, proxies) try: - host_params, pool_kwargs = _urllib3_request_context(request, verify) + host_params, pool_kwargs = _urllib3_request_context(request, verify, cert) except ValueError as e: raise InvalidURL(e, request=request) if proxy: @@ -509,7 +519,7 @@ def send( """ try: - conn = self._get_connection(request, verify, proxies) + conn = self._get_connection(request, verify, proxies=proxies, cert=cert) except LocationValueError as e: raise InvalidURL(e, request=request) diff --git a/tests/certs/README.md b/tests/certs/README.md new file mode 100644 index 0000000000..4bf7002e0b --- /dev/null +++ b/tests/certs/README.md @@ -0,0 +1,10 @@ +# Testing Certificates + +This is a collection of certificates useful for testing aspects of Requests' +behaviour. + +The certificates include: + +* [expired](./expired) server certificate with a valid certificate authority +* [mtls](./mtls) provides a valid client certificate with a 2 year validity +* [valid](./valid) has a valid server certificate diff --git a/tests/certs/expired/Makefile b/tests/certs/expired/Makefile new file mode 100644 index 0000000000..d5a51da541 --- /dev/null +++ b/tests/certs/expired/Makefile @@ -0,0 +1,13 @@ +.PHONY: all clean ca server + +ca: + make -C $@ all + +server: + make -C $@ all + +all: ca server + +clean: + make -C ca clean + make -C server clean diff --git a/tests/certs/expired/README.md b/tests/certs/expired/README.md new file mode 100644 index 0000000000..f7234f8820 --- /dev/null +++ b/tests/certs/expired/README.md @@ -0,0 +1,11 @@ +# Expired Certificates and Configuration for Testing + +This has a valid certificate authority in [ca](./ca) and an invalid server +certificate in [server](./server). + +This can all be regenerated with: + +``` +make clean +make all +``` diff --git a/tests/certs/expired/ca/Makefile b/tests/certs/expired/ca/Makefile new file mode 100644 index 0000000000..098193f88d --- /dev/null +++ b/tests/certs/expired/ca/Makefile @@ -0,0 +1,13 @@ +.PHONY: all clean + +root_files = ca-private.key ca.crt + +ca-private.key: + openssl genrsa -out ca-private.key 2048 + +all: ca-private.key + openssl req -x509 -sha256 -days 7300 -key ca-private.key -out ca.crt -config ca.cnf + ln -s ca.crt cacert.pem + +clean: + rm -f cacert.pem ca.crt ca-private.key *.csr diff --git a/tests/certs/expired/ca/ca-private.key b/tests/certs/expired/ca/ca-private.key new file mode 100644 index 0000000000..507b1f5623 --- /dev/null +++ b/tests/certs/expired/ca/ca-private.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHlIhe7GLCeSk8 +RZOKdtmyKns6KdZgGw/LcxPkYvQlu1g0zV8X0DqVr2LdMumWUTNCc9sPdSlAG+He +mQp2TMoWUMumMuwDtit9RT0Sb6Eh9svWgjY9ferovPJRfCWUTsA2Ug8uoh0wyEXK +na7X6fHt5E3B9vj0+b9a4vDibdBXV11FheLT02/uEmAEJDdP/zeBgvVbhcVyumO6 +fAGMIWzR2ukhe8z/ma5H9zoi4gZA8nsK6reZUD8+6affnPe+jIt/AdzggtV9jkWm +zSpr+RHeZ0y+q4eik2ZNUGg4XcF6JsJ9yu/AqLBXxd38uLdFfgyhP2y6K628yzgy +e6lzFyWnAgMBAAECggEAFwzHhzcD3PQDWCus85PwZoxTeQ817BmUBGpBBOKM0gLG +GCsT7XsmGP2NjICBy9OK+QTKawmb/wR5XK0OMUWDHXqtWn+NFIyojyo8+HEeCf8n +4ZleTFHLnJ+d2N1etbc2qc9mY3tjpaurq8/0Tol9YH06ock1TY2+lO+a5HvMURnY +hcWs70CamL+5B/6n67DhjzMtIW3dIXuEEceM1BW/jW8SKq0JHpQ3t+OJwID7zFaJ +bLyOwAVheMzVGvN3yphf8tll3tMA65bNjdOzgOfZSjAy7EGjW3DyAolDw9jKLRyu +E0gw/exNGe618oMIeUDv0KParlL4RjdiUP8l0xYOwQKBgQD3eYj9rWeqZquI9vKP +gaSv6urb2UJLngShZUpEZRNJgBO+Ewiof0w8tpQdsnuMvWudxMLbzgiUNA+NyC/K +CpzIXFkWnWx+A/pxs8ZO8moOfajVRayJgeOLsQZb7c4fXGsVGApbN4+cPNhTNG6d +ucErv6tae/SzAzcLc5Vkw/ELxwKBgQDOdJ5Wl5JeKAvU/3kF6+MYWCrXxZqMjoHS +y1BtyMX5RbdaWTCfDUu1aV3qJOJjjWQ9DJdJQcEsrTjOpD4bVdZx4w/XEG0JXAa3 +jRypVHGdeG/TjhUGJA8U+KX3a1DkcdqM9pqFYRw5Ie95Wz9YRroI+YkixqpK8d7W +C+5BodxXIQKBgCk8Lv9V7XgPM3XW8APJbk+BrTCEuu8unUbnQcCztssAdEmvkjnB +PErBgVyRaNTCmzPmnTFS20sWgaD2QkBAFG+uM4n5ISK+NvTLJ7fv3IwdlAw1V9Jx +uiCElrKqpTXEiHMzVkZss5ks6j6y9duCIBXSEhM5pERPvNRDphjsLTXxAoGARSNC +nyb1Kjjo9XR0V+pNy6pC9q1C+00B5tCVZ55zxe114Hi70pfGQcM+YxnlAoeoCNW9 +mBfAFDESNAlGjyrovIzYkiH7EcZSrYdBEOepgJ2DfWo4Wi0bK9+03K2AknAaS1iO +GJqTtAJMSuymwu40gKroJNA42Q40nKO0LyCARGECgYEAiFRHkblBtStv22SpZxNC +jim9yuM0ikh7Ij1lEHysc/GWb2RQNxQVk54BU2kQ0d9xwMZQTKvpF3VE9t7uGdwt +AasWPr/tWYt35Ud0D4bNlagJJ4Xdslf8n1nkq3qqqDQbd7kkQRgwGzVr0uVg7ZfS +26qSPQ0/aF9nagb5eHX3AuU= +-----END PRIVATE KEY----- diff --git a/tests/certs/expired/ca/ca.cnf b/tests/certs/expired/ca/ca.cnf new file mode 100644 index 0000000000..8c4b823053 --- /dev/null +++ b/tests/certs/expired/ca/ca.cnf @@ -0,0 +1,12 @@ +[req] +default_bits = 2048 +prompt = no +default_md = sha256 +encrypt_key = no +distinguished_name = dn + +[dn] +C = US # country code +O = Python Software Foundation # organization +OU = python-requests # organization unit/department +CN = Self-Signed Root CA # common name / your cert name diff --git a/tests/certs/expired/ca/ca.crt b/tests/certs/expired/ca/ca.crt new file mode 100644 index 0000000000..c332b7cb7b --- /dev/null +++ b/tests/certs/expired/ca/ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWzCCAkMCFA9wdtNh/V99DRwYp8vXjPxSjJnWMA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAlVTMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlv +bjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRwwGgYDVQQDDBNTZWxmLVNpZ25l +ZCBSb290IENBMB4XDTI0MDMxMjIxMDQwM1oXDTQ0MDMwNzIxMDQwM1owajELMAkG +A1UEBhMCVVMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRgw +FgYDVQQLDA9weXRob24tcmVxdWVzdHMxHDAaBgNVBAMME1NlbGYtU2lnbmVkIFJv +b3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHlIhe7GLCeSk8 +RZOKdtmyKns6KdZgGw/LcxPkYvQlu1g0zV8X0DqVr2LdMumWUTNCc9sPdSlAG+He +mQp2TMoWUMumMuwDtit9RT0Sb6Eh9svWgjY9ferovPJRfCWUTsA2Ug8uoh0wyEXK +na7X6fHt5E3B9vj0+b9a4vDibdBXV11FheLT02/uEmAEJDdP/zeBgvVbhcVyumO6 +fAGMIWzR2ukhe8z/ma5H9zoi4gZA8nsK6reZUD8+6affnPe+jIt/AdzggtV9jkWm +zSpr+RHeZ0y+q4eik2ZNUGg4XcF6JsJ9yu/AqLBXxd38uLdFfgyhP2y6K628yzgy +e6lzFyWnAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGymNVTsKSAq8Ju6zV+AWAyV +GcUNBmLpgzDA0e7pkVYhHTdWKlGH4GnrRcp0nvnSbr6iq1Ob/8yEUUoRzK55Flws +Kt1OLwnZyhfRoSUesoEqpP68vzWEgiYv0QuIWvzNt0YfAAvEgGoc3iri44MelKLn +9ZMT8m91nVamA35R8ZjfeAkNp2xcz0a67V0ww6o4wSXrG7o5ZRXyjqZ/9K7SfwUJ +rV9RciccsjH/MzKbfrx73QwsbPWiFmjzHopdasIO0lDlmgm/r9gKfkbzfKoGCgLZ +6an6FlmLftLSXijf/QwtqeSP9fODeE3dzBmnTM3jdoVS53ZegUDWNl14o25v2Kg= +-----END CERTIFICATE----- diff --git a/tests/certs/expired/ca/ca.srl b/tests/certs/expired/ca/ca.srl new file mode 100644 index 0000000000..fab68405ed --- /dev/null +++ b/tests/certs/expired/ca/ca.srl @@ -0,0 +1 @@ +4F36C3A7E075BA6452D10EEB81E7F189FF489B74 diff --git a/tests/certs/expired/server/Makefile b/tests/certs/expired/server/Makefile new file mode 100644 index 0000000000..79914ee1db --- /dev/null +++ b/tests/certs/expired/server/Makefile @@ -0,0 +1,16 @@ +.PHONY: all clean + +server.key: + openssl genrsa -out $@ 2048 + +server.csr: server.key + openssl req -key $< -new -out $@ -config cert.cnf + +server.pem: server.csr + openssl x509 -req -CA ../ca/ca.crt -CAkey ../ca/ca-private.key -in server.csr -outform PEM -out server.pem -days 0 -CAcreateserial + openssl x509 -in ../ca/ca.crt -outform PEM >> $@ + +all: server.pem + +clean: + rm -f server.* diff --git a/tests/certs/expired/server/cert.cnf b/tests/certs/expired/server/cert.cnf new file mode 100644 index 0000000000..a773fc679f --- /dev/null +++ b/tests/certs/expired/server/cert.cnf @@ -0,0 +1,24 @@ +[req] +req_extensions = v3_req +distinguished_name = req_distinguished_name +prompt=no + +[req_distinguished_name] +C = US +ST = DE +O = Python Software Foundation +OU = python-requests +CN = localhost + +[v3_req] +# Extensions to add to a certificate request +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = @alt_names + +[alt_names] +DNS.1 = *.localhost +DNS.1 = localhost +IP.1 = 127.0.0.1 +IP.2 = ::1 diff --git a/tests/certs/expired/server/server.csr b/tests/certs/expired/server/server.csr new file mode 100644 index 0000000000..5e3c177647 --- /dev/null +++ b/tests/certs/expired/server/server.csr @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDHjCCAgYCAQAwbTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkRFMSMwIQYDVQQK +DBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEYMBYGA1UECwwPcHl0aG9uLXJl +cXVlc3RzMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCKulIMpo633iCgbkKv1UoiLC4sQt5xWpgguujywu3hLYwmPFp9 +kvPt//imqtl8FhuhKqJ8FCGrVl2YIGj1RJIB3GW7MSPNCuIBFL/gwNi35LxDPtoA +IPyXytIR7VH9+ch9DFInJaoA/BekMuKvbXk54VW9whpHbwkXSG2lBS2vKL0XemYh +9VjvtuRDji2iOZpznlVE2PEN80bojArp6oYKakv2kYzgzgxAJiI/NZGvC7mbSI4e +ja7ad3R9G0kB1FzNj36jrNO5WtxHO/mrRiXSpDeyUbitYvt0HKoM0vhTnOR+BspP +IltfwOQh8qq2Q2AaMHNcVjMH3gHCZADfhk/zAgMBAAGgbDBqBgkqhkiG9w0BCQ4x +XTBbMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMB +MCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATAN +BgkqhkiG9w0BAQsFAAOCAQEAfAhEhrulsZae71YFqgvzwJHm/hzXh47hErtgDXVJ +mFqAxgF6XrnzYujlt3XQXUx/8vdrU7jH+Pe8WO1rDvFwRPMDGoBF3RX29SzyX/2F +e102egnoRR+Hlf0Ixqu0CuTjEVnD+g4mRgXhV7LPKP4W6qGwzcVbaJ3c/zRcfqNR +g9gN6Q6Qt4fXDc7wlx2T3nOszBLQ2XCsIyzVtOJ2sSuadqKH9Aj+mrkrLBdzVFHD +FHnTMJ0t0+anZwd+AWDNsCr5lIwBGL634zw7/yJepMHuPFd2X24S3u8EaWPkfVQn +lV6rLQMGjXYTe2xuYzlUCUYnKvkyPTMjSXDkxWa+WSNwyQ== +-----END CERTIFICATE REQUEST----- diff --git a/tests/certs/expired/server/server.key b/tests/certs/expired/server/server.key new file mode 100644 index 0000000000..27ddafd1ca --- /dev/null +++ b/tests/certs/expired/server/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCKulIMpo633iCg +bkKv1UoiLC4sQt5xWpgguujywu3hLYwmPFp9kvPt//imqtl8FhuhKqJ8FCGrVl2Y +IGj1RJIB3GW7MSPNCuIBFL/gwNi35LxDPtoAIPyXytIR7VH9+ch9DFInJaoA/Bek +MuKvbXk54VW9whpHbwkXSG2lBS2vKL0XemYh9VjvtuRDji2iOZpznlVE2PEN80bo +jArp6oYKakv2kYzgzgxAJiI/NZGvC7mbSI4eja7ad3R9G0kB1FzNj36jrNO5WtxH +O/mrRiXSpDeyUbitYvt0HKoM0vhTnOR+BspPIltfwOQh8qq2Q2AaMHNcVjMH3gHC +ZADfhk/zAgMBAAECggEAFSF9RvUFzyb0BEvXN44+/QaKv+4tkMmSW4Xs3rFnZ4G3 +E8nkpLUCF9ICD2z9tKNvcPScDFdKq5z7o6ToJ9faf5MRIdrBz8UlGLIO6g6l1Bjw +vjNwJE3h+8MGjXl/IDbwXW/HgbQAeabsePPRSJRdvz2+ACn1M8VLdrLvFJA93ayW ++n3Bk0bXdsrzqBGdoDiNzmIHI3WqdONiR9TymuJe41NJtMKxQDF+c6Y1n/X1OtBk +s9L+u9Xr+R3H72xSYrf1KH1mFZJfTnIPoOmdEU2tVZnZj03rZhT7p8R1fVNX6OHu +NX1Dy9VA6J7dbcqdPvTI743ByQeb+hNnqI/3hmV5eQKBgQC++1Wn3v/dxtczjA+I +tN4a7zyjhazpB25lde55HVfCQPxmYxIYct+j6S0JkMaoLrjiEDb4pnu4Gt4MDqZa +r0Xm8t3wD1YKUUbhpBEGvsMhAEZEIsBOcwkTiEwsoF0mKFa2mTyqAImgIQa8uFt8 +Y/oTj55XFe1x6pZKEJRg+K+QSwKBgQC59ONVkMSBirLGS+G+b2kqiBdwZB/3s3wr +feS1xTa+deL3AChnKT9+MsVqOkxdE2TRj/mAeF+5Woa5bPMvgr9Kl7u8bulTH80l +YA/N6FneO11/ncnkgK9wN54kd5TiOtGsGB5S5t/nEAIMUIwWrM/cRau72xNEWOhT +Tvw7TOSF+QKBgQCa/texeiYmE24sA4vH4yIuseKAw8hlBwbtiRyVZt8GZD9zyQuy +k+g02tUWYk0XyXN65LX4bwURkZyMJIeWKZGNsaW1YnzturDQB5tZ4g/zBIoCWkHA +aVQAaimIPk3a3foiD5NQVUdckfEp0GVPOsSGg5R6EO23+i8mxPXnDW1OqQKBgGvf +lelTO8tyLFdAOcqBUt6rZ/1499p3snaAZ6bSqvk95dYnr0h48y5AQaln/FiaIYg4 +HyLZsZ4S18jFXSWYkWOyNeQP6yafciBWY5StT0TN52VaoX3+8McGXKUHAcVjHbLZ +ou2wpP6jmKyQJVQaF9LOT9uAMOMbOFrrnQLBjmfxAoGAQAnUhMFG5mwi9Otxt6Mz +g+Gr+3JTlzwC3L7UwGdlFc3G2vSdGx/yOrfzpxPImfIBS95mibDfdvEBMer26pvw +a/ycqybyX9d/5nPDIaJ1lc4M4cbHC/cB52JI6avr/1g8OMK7lR7b/FsPVHS1w8kl +n6uwEjVt2+gP2o9DFTGs158= +-----END PRIVATE KEY----- diff --git a/tests/certs/expired/server/server.pem b/tests/certs/expired/server/server.pem new file mode 100644 index 0000000000..05a2a4dac8 --- /dev/null +++ b/tests/certs/expired/server/server.pem @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIDXjCCAkYCFE82w6fgdbpkUtEO64Hn8Yn/SJt0MA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAlVTMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlv +bjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRwwGgYDVQQDDBNTZWxmLVNpZ25l +ZCBSb290IENBMB4XDTI0MDMxMzIxMTQ0NVoXDTI0MDMxMzIxMTQ0NVowbTELMAkG +A1UEBhMCVVMxCzAJBgNVBAgMAkRFMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUg +Rm91bmRhdGlvbjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRIwEAYDVQQDDAls +b2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCKulIMpo63 +3iCgbkKv1UoiLC4sQt5xWpgguujywu3hLYwmPFp9kvPt//imqtl8FhuhKqJ8FCGr +Vl2YIGj1RJIB3GW7MSPNCuIBFL/gwNi35LxDPtoAIPyXytIR7VH9+ch9DFInJaoA +/BekMuKvbXk54VW9whpHbwkXSG2lBS2vKL0XemYh9VjvtuRDji2iOZpznlVE2PEN +80bojArp6oYKakv2kYzgzgxAJiI/NZGvC7mbSI4eja7ad3R9G0kB1FzNj36jrNO5 +WtxHO/mrRiXSpDeyUbitYvt0HKoM0vhTnOR+BspPIltfwOQh8qq2Q2AaMHNcVjMH +3gHCZADfhk/zAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGeQdB4+iDbJ78eKhCMV +49Cm8nyYi9215rRRJ24Bw6BtVw1ECwymxLVOEB0gHCu8kKdsFnniFBtChts/ilFg +blIyPKTsb3+kQW9YV9QwVdFdC4mTIljujCSQ4HNUC/Vjfnz85SDKf9/3PMKRr36+ +GtSLIozudPvkNmCv68jy3RRXyCwWHc43BLMSZKPD/W+DEuXShI9OIpIlSLBx16Hz +4ce3/1pGuITWcsw6UcRqW31oPR31QmNs5fsq5ZCojDNFzEFCA1t9LiR6UOftFUKy +yOZWfZeAGGdK75U+XDqS9Xkr5/ic5jE0I5rT7e7r3lpvQdgIj8lSx493fczLOGHr +YA0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDWzCCAkMCFA9wdtNh/V99DRwYp8vXjPxSjJnWMA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAlVTMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlv +bjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRwwGgYDVQQDDBNTZWxmLVNpZ25l +ZCBSb290IENBMB4XDTI0MDMxMjIxMDQwM1oXDTQ0MDMwNzIxMDQwM1owajELMAkG +A1UEBhMCVVMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRgw +FgYDVQQLDA9weXRob24tcmVxdWVzdHMxHDAaBgNVBAMME1NlbGYtU2lnbmVkIFJv +b3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHlIhe7GLCeSk8 +RZOKdtmyKns6KdZgGw/LcxPkYvQlu1g0zV8X0DqVr2LdMumWUTNCc9sPdSlAG+He +mQp2TMoWUMumMuwDtit9RT0Sb6Eh9svWgjY9ferovPJRfCWUTsA2Ug8uoh0wyEXK +na7X6fHt5E3B9vj0+b9a4vDibdBXV11FheLT02/uEmAEJDdP/zeBgvVbhcVyumO6 +fAGMIWzR2ukhe8z/ma5H9zoi4gZA8nsK6reZUD8+6affnPe+jIt/AdzggtV9jkWm +zSpr+RHeZ0y+q4eik2ZNUGg4XcF6JsJ9yu/AqLBXxd38uLdFfgyhP2y6K628yzgy +e6lzFyWnAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGymNVTsKSAq8Ju6zV+AWAyV +GcUNBmLpgzDA0e7pkVYhHTdWKlGH4GnrRcp0nvnSbr6iq1Ob/8yEUUoRzK55Flws +Kt1OLwnZyhfRoSUesoEqpP68vzWEgiYv0QuIWvzNt0YfAAvEgGoc3iri44MelKLn +9ZMT8m91nVamA35R8ZjfeAkNp2xcz0a67V0ww6o4wSXrG7o5ZRXyjqZ/9K7SfwUJ +rV9RciccsjH/MzKbfrx73QwsbPWiFmjzHopdasIO0lDlmgm/r9gKfkbzfKoGCgLZ +6an6FlmLftLSXijf/QwtqeSP9fODeE3dzBmnTM3jdoVS53ZegUDWNl14o25v2Kg= +-----END CERTIFICATE----- diff --git a/tests/certs/mtls/Makefile b/tests/certs/mtls/Makefile new file mode 100644 index 0000000000..399a906da7 --- /dev/null +++ b/tests/certs/mtls/Makefile @@ -0,0 +1,7 @@ +.PHONY: all clean + +all: + make -C client all + +clean: + make -C client clean diff --git a/tests/certs/mtls/README.md b/tests/certs/mtls/README.md new file mode 100644 index 0000000000..9a3df4623e --- /dev/null +++ b/tests/certs/mtls/README.md @@ -0,0 +1,4 @@ +# Certificate Examples for mTLS + +This has some generated certificates for mTLS utilization. The idea is to be +able to have testing around how Requests handles client certificates. diff --git a/tests/certs/mtls/client/Makefile b/tests/certs/mtls/client/Makefile new file mode 100644 index 0000000000..9c6c388be1 --- /dev/null +++ b/tests/certs/mtls/client/Makefile @@ -0,0 +1,16 @@ +.PHONY: all clean + +client.key: + openssl genrsa -out $@ 2048 + +client.csr: client.key + openssl req -key $< -new -out $@ -config cert.cnf + +client.pem: client.csr + openssl x509 -req -CA ./ca/ca.crt -CAkey ./ca/ca-private.key -in client.csr -outform PEM -out client.pem -days 730 -CAcreateserial + openssl x509 -in ./ca/ca.crt -outform PEM >> $@ + +all: client.pem + +clean: + rm -f client.* diff --git a/tests/certs/mtls/client/ca b/tests/certs/mtls/client/ca new file mode 120000 index 0000000000..85c8e8f2c2 --- /dev/null +++ b/tests/certs/mtls/client/ca @@ -0,0 +1 @@ +../../expired/ca/ \ No newline at end of file diff --git a/tests/certs/mtls/client/cert.cnf b/tests/certs/mtls/client/cert.cnf new file mode 100644 index 0000000000..338e2527ba --- /dev/null +++ b/tests/certs/mtls/client/cert.cnf @@ -0,0 +1,26 @@ +[req] +req_extensions = v3_req +distinguished_name = req_distinguished_name +prompt=no + +[req_distinguished_name] +C = US +ST = DE +O = Python Software Foundation +OU = python-requests +CN = requests + +[v3_req] +# Extensions to add to a certificate request +basicConstraints = CA:FALSE +keyUsage = digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth +subjectAltName = @alt_names + +[alt_names] +DNS.1 = *.localhost +IP.1 = 127.0.0.1 +IP.2 = ::1 +URI.1 = spiffe://trust.python.org/v0/maintainer/sigmavirus24/project/requests/org/psf +URI.2 = spiffe://trust.python.org/v1/maintainer:sigmavirus24/project:requests/org:psf +URI.3 = spiffe://trust.python.org/v1/maintainer=sigmavirus24/project=requests/org=psf diff --git a/tests/certs/mtls/client/client.csr b/tests/certs/mtls/client/client.csr new file mode 100644 index 0000000000..9a5713d5c7 --- /dev/null +++ b/tests/certs/mtls/client/client.csr @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEGjCCAwICAQAwbDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkRFMSMwIQYDVQQK +DBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEYMBYGA1UECwwPcHl0aG9uLXJl +cXVlc3RzMREwDwYDVQQDDAhyZXF1ZXN0czCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMn3iQycTjUzpKJChRNkcm33UB282cUwpxeqKN4ahHxBpS09HRhk +cQYO7yErEUQwzQnBQEcIpzzeIMZIqHuCkgnySjeEJd95AIzNzGyoLLkS51TcJwgR +v83AvT8ljA88s9h38qGTy4/TCxJgf76pfHIuC1qoKVQh3AuHj9nOxIZLUsrdDbWF +WoLqKSVyTby+RXvSAppAR+cuBCaWStQ6xFORn48RHfc6t30ggD4rDAjyU6Vz6oR8 +ot3XmGdK0h42UdqidUWkRJajEbpkCnQSXS21IvfXKxF5sFqAXJrj9iVbUfpNPpaa +W8IrHByngyV8amazGZrASstUVRFtWrnrcWECAwEAAaCCAWcwggFjBgkqhkiG9w0B +CQ4xggFUMIIBUDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDAjCCAR8GA1UdEQSCARYwggESggsqLmxvY2FsaG9zdIcEfwAAAYcQAAAA +AAAAAAAAAAAAAAAAAYZNc3BpZmZlOi8vdHJ1c3QucHl0aG9uLm9yZy92MC9tYWlu +dGFpbmVyL3NpZ21hdmlydXMyNC9wcm9qZWN0L3JlcXVlc3RzL29yZy9wc2aGTXNw +aWZmZTovL3RydXN0LnB5dGhvbi5vcmcvdjEvbWFpbnRhaW5lcjpzaWdtYXZpcnVz +MjQvcHJvamVjdDpyZXF1ZXN0cy9vcmc6cHNmhk1zcGlmZmU6Ly90cnVzdC5weXRo +b24ub3JnL3YxL21haW50YWluZXI9c2lnbWF2aXJ1czI0L3Byb2plY3Q9cmVxdWVz +dHMvb3JnPXBzZjANBgkqhkiG9w0BAQsFAAOCAQEAwP1KJ+Evddn2RV1FM6BFkoDK +MPDO9qwb8ea3j57SIJXZlpw168DljmuGzxJw9oys2O6FYcspbHIocAkfFwiYgVAr +NEog6xlCdPxNBJgC3YFIKwnmBjMPG6ZCWiJn940qTbaJ/j6ZviN17uW4K7Sl+THp +IkMv29uQTWkfg+GbZ9q1hm2m2GHhYLGLAUdJdtv7JI+yq5uxdsWaCANpH6kc8SnK +2rik6D3iItDhHCmToHBpdEnP8J+KDzf5pJrv/g3WH8XVrl4ZzBsOhmciWF4C3Hbf +9eu8eAsp1AsIrZOEGTfClBd7vFCES5DmI0/iRs4czQooqZPnHjOw3Azp/LujrA== +-----END CERTIFICATE REQUEST----- diff --git a/tests/certs/mtls/client/client.key b/tests/certs/mtls/client/client.key new file mode 100644 index 0000000000..8107125399 --- /dev/null +++ b/tests/certs/mtls/client/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDJ94kMnE41M6Si +QoUTZHJt91AdvNnFMKcXqijeGoR8QaUtPR0YZHEGDu8hKxFEMM0JwUBHCKc83iDG +SKh7gpIJ8ko3hCXfeQCMzcxsqCy5EudU3CcIEb/NwL0/JYwPPLPYd/Khk8uP0wsS +YH++qXxyLgtaqClUIdwLh4/ZzsSGS1LK3Q21hVqC6iklck28vkV70gKaQEfnLgQm +lkrUOsRTkZ+PER33Ord9IIA+KwwI8lOlc+qEfKLd15hnStIeNlHaonVFpESWoxG6 +ZAp0El0ttSL31ysRebBagFya4/YlW1H6TT6WmlvCKxwcp4MlfGpmsxmawErLVFUR +bVq563FhAgMBAAECggEABhWX97JJxN6JFNOjhgGzqiPA3R8lrFlv3zhNbODS9u9U +q404xYBZIKaYhkucLzgNJUBrevhZbsL+V8WJQIH0JlU57nw5ATIjAHA+uqiXraen +zRhTcLHK28b1AeRUA4LU+YN7jWnnawN075kf9WgjtfOJ0gcDimOkE7uCFjyyvPJA +LG9bG+8enGjvUleKXNgmwP4Sq/GlEdGz9Qy+8ga3mtfAULUWe8haFNZXK8CN3xPp +wmVqy7QzgH2TGN1p6Dyxib9ksSN/lOg0dShL8zgu+QXDNx2VwmVrI8Vr02vmB//0 +bYxCo5pfICPIFLjLl5yo30dvrUfYqF29PperStHGlQKBgQD/TdemlLjJNP0fvSs7 +KEVJj/22YuHK+wurNr2ZFbSdcF3v9sfiwysllmEyGr5cNYA56uUbfG+8VSw7kDll +G+6BKK2UdlPH++6RahqWLqo4k6rsNrkq7elj8xG4gIjR5qzu2uLpjNwp2BGmIoUI +eb1NcLfTlMcNCooV8RHjm1Z5WwKBgQDKhHkUPDcJm2/9Ltq2NZQMrCS7o4LV2uAI +GhGpISfY+SfHkQQNZ9Fvbe6hrFeZs31nAvlTDpPEg/LGSVKA5I2EZT9gwzAQU1TD +Cyol4xqqWFWlwze7w+RLYqX5LtXf7NJg2m5p+ZOoOzzqvTVpodDxqTlCNp2/6ICP +vAIvWhbA8wKBgAYlr62ZIyHlHrsm6OWRwKlWyDseAmXKyasjtEj9Vs37qKdgf8ub ++2v6RPjZ3/+EYkQCveV9h4s3WctNW7Rtib6eZh+PAdFs5X+m2GEJWpvmIlVxs9+u +vtHjRmf04FZ9gWh26MPK2no/c51Wc3GSzNYSgrqbeHd963k/xrh+QwTFAoGAZZjb +3UjwG4O9RPjyhCKQ6WKa8v9urbamWaoqXfziLrmgOUAJFmiU6x/tbXI2aEdhjAIz +7nULsLS5YLx8BWmjjV3106dYP3hut4KsXGF4iSjTnts25J27tA4DUeUrKrF2QVyT +s9qfNvCw+Np/J0Uku3e33/3iWdpcVL9vIS5C5/0CgYBEuxb3dffNRqEiNkpOUrCD +mQTqbO3X+hin9zT3GrxQE+7KpfCfdDIqdK6c5UWHirR3HUjUPZmIFLSx8msfLl3k +hgQw37NMV+asg0Wy3P908qbtnEA2P6aDOMQeHJoC7qEHIDOcOQ1KP3FMvOrdscwS +f0IIDygTH6fYr329s0iXjg== +-----END PRIVATE KEY----- diff --git a/tests/certs/mtls/client/client.pem b/tests/certs/mtls/client/client.pem new file mode 100644 index 0000000000..0a11d4d472 --- /dev/null +++ b/tests/certs/mtls/client/client.pem @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkUCFE82w6fgdbpkUtEO64Hn8Yn/SJtzMA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAlVTMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlv +bjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRwwGgYDVQQDDBNTZWxmLVNpZ25l +ZCBSb290IENBMB4XDTI0MDMxMzE4MzUwNFoXDTI2MDMxMzE4MzUwNFowbDELMAkG +A1UEBhMCVVMxCzAJBgNVBAgMAkRFMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUg +Rm91bmRhdGlvbjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMREwDwYDVQQDDAhy +ZXF1ZXN0czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMn3iQycTjUz +pKJChRNkcm33UB282cUwpxeqKN4ahHxBpS09HRhkcQYO7yErEUQwzQnBQEcIpzze +IMZIqHuCkgnySjeEJd95AIzNzGyoLLkS51TcJwgRv83AvT8ljA88s9h38qGTy4/T +CxJgf76pfHIuC1qoKVQh3AuHj9nOxIZLUsrdDbWFWoLqKSVyTby+RXvSAppAR+cu +BCaWStQ6xFORn48RHfc6t30ggD4rDAjyU6Vz6oR8ot3XmGdK0h42UdqidUWkRJaj +EbpkCnQSXS21IvfXKxF5sFqAXJrj9iVbUfpNPpaaW8IrHByngyV8amazGZrASstU +VRFtWrnrcWECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAHHgMckLDRV72p1FEVmCh +AAPZjCswiPZFrwGPN57JqSWjoRB9ilKvo87aPosEO7vfa05OD/qkM/T9Qykuhati +I1T1T7qX4Ymb5kTJIBouuflAO3uKVaq+ga2Q/HLlU5w/VoMU4RuK7+RaiRUEE3xL +iPSMBvZpoMj695LnzcGrT5oLkFI0bTIlpQt1SFjDpHFtOj/ZdwgSbZYLoTCBXQK3 +7Y29qAj/XwEiCH63n8tJKvZcD8/ssMIMIdWhNmu+0jOWica/3WSih9Geoy6Ydtxi +I5t9vRjC4LIipMUAF86AJIfvHJyI6aCNT420LaR6NRW0FQn5CPTHPAsKg3JkAywn +Ew== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDWzCCAkMCFA9wdtNh/V99DRwYp8vXjPxSjJnWMA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAlVTMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlv +bjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRwwGgYDVQQDDBNTZWxmLVNpZ25l +ZCBSb290IENBMB4XDTI0MDMxMjIxMDQwM1oXDTQ0MDMwNzIxMDQwM1owajELMAkG +A1UEBhMCVVMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRgw +FgYDVQQLDA9weXRob24tcmVxdWVzdHMxHDAaBgNVBAMME1NlbGYtU2lnbmVkIFJv +b3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHlIhe7GLCeSk8 +RZOKdtmyKns6KdZgGw/LcxPkYvQlu1g0zV8X0DqVr2LdMumWUTNCc9sPdSlAG+He +mQp2TMoWUMumMuwDtit9RT0Sb6Eh9svWgjY9ferovPJRfCWUTsA2Ug8uoh0wyEXK +na7X6fHt5E3B9vj0+b9a4vDibdBXV11FheLT02/uEmAEJDdP/zeBgvVbhcVyumO6 +fAGMIWzR2ukhe8z/ma5H9zoi4gZA8nsK6reZUD8+6affnPe+jIt/AdzggtV9jkWm +zSpr+RHeZ0y+q4eik2ZNUGg4XcF6JsJ9yu/AqLBXxd38uLdFfgyhP2y6K628yzgy +e6lzFyWnAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGymNVTsKSAq8Ju6zV+AWAyV +GcUNBmLpgzDA0e7pkVYhHTdWKlGH4GnrRcp0nvnSbr6iq1Ob/8yEUUoRzK55Flws +Kt1OLwnZyhfRoSUesoEqpP68vzWEgiYv0QuIWvzNt0YfAAvEgGoc3iri44MelKLn +9ZMT8m91nVamA35R8ZjfeAkNp2xcz0a67V0ww6o4wSXrG7o5ZRXyjqZ/9K7SfwUJ +rV9RciccsjH/MzKbfrx73QwsbPWiFmjzHopdasIO0lDlmgm/r9gKfkbzfKoGCgLZ +6an6FlmLftLSXijf/QwtqeSP9fODeE3dzBmnTM3jdoVS53ZegUDWNl14o25v2Kg= +-----END CERTIFICATE----- diff --git a/tests/certs/valid/ca b/tests/certs/valid/ca new file mode 120000 index 0000000000..46f26c3982 --- /dev/null +++ b/tests/certs/valid/ca @@ -0,0 +1 @@ +../expired/ca \ No newline at end of file diff --git a/tests/certs/valid/server/Makefile b/tests/certs/valid/server/Makefile new file mode 100644 index 0000000000..9ce6778c0f --- /dev/null +++ b/tests/certs/valid/server/Makefile @@ -0,0 +1,16 @@ +.PHONY: all clean + +server.key: + openssl genrsa -out $@ 2048 + +server.csr: server.key + openssl req -key $< -config cert.cnf -new -out $@ + +server.pem: server.csr + openssl x509 -req -CA ../ca/ca.crt -CAkey ../ca/ca-private.key -in server.csr -outform PEM -out server.pem -extfile cert.cnf -extensions v3_ca -days 7200 -CAcreateserial + openssl x509 -in ../ca/ca.crt -outform PEM >> $@ + +all: server.pem + +clean: + rm -f server.* diff --git a/tests/certs/valid/server/cert.cnf b/tests/certs/valid/server/cert.cnf new file mode 100644 index 0000000000..f9a01cd8b4 --- /dev/null +++ b/tests/certs/valid/server/cert.cnf @@ -0,0 +1,31 @@ +[req] +req_extensions = v3_req +distinguished_name = req_distinguished_name +prompt=no + +[req_distinguished_name] +C = US +ST = DE +O = Python Software Foundation +OU = python-requests +CN = localhost + +[v3_req] +# Extensions to add to a certificate request +basicConstraints = critical, CA:FALSE +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = critical, serverAuth +subjectAltName = critical, @alt_names + +[v3_ca] +# Extensions to add to a certificate request +basicConstraints = critical, CA:FALSE +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = critical, serverAuth +subjectAltName = critical, @alt_names + +[alt_names] +DNS.1 = *.localhost +DNS.1 = localhost +IP.1 = 127.0.0.1 +IP.2 = ::1 diff --git a/tests/certs/valid/server/server.csr b/tests/certs/valid/server/server.csr new file mode 100644 index 0000000000..000d1facb2 --- /dev/null +++ b/tests/certs/valid/server/server.csr @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDKjCCAhICAQAwbTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkRFMSMwIQYDVQQK +DBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEYMBYGA1UECwwPcHl0aG9uLXJl +cXVlc3RzMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQChEKOx377ymuDg23By5Re1DHi2RiBKSHr85/ZTZuwP/69lHN7q +TQEO//EMEFZ9+ZwezeJJsejjP2HO5lQZbcsWok3hbM0wVT+vApkogPvJ8WNFFWFe +ZBnGLi/1WM9cSZpUsDJ0XCsG0RTtO27wfgZQlKQMZxTkfi971oPYxNVSjTm2JcLT +kvwYIwxjJXPDTOgRo9TEAY3cWkCrBJN4w74GWBTM5KDDA230T7WwLuv81XD2LvYj +YYdMBGcxPr5tYTIlp3LncbcrDRNk3pbYQk0bRJgkw2vUkteiRGjkt+dgVnLc6+MI +W+VLXEpj+zsOZ5/R4d1pofqj9sDyDPhtNr1JAgMBAAGgeDB2BgkqhkiG9w0BCQ4x +aTBnMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBYGA1UdJQEB/wQMMAoG +CCsGAQUFBwMBMC8GA1UdEQEB/wQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAA +AAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAFTlFTn5Mn8JXtqB5bGjuiChe +ClA6Y32Co4l7N0CtAlf+bExwLdpLOleTX3WnryIPALl9uBUI/67dy/STn/J1Yn86 +jWPEFwpmYNSKgQljYWcwtBdYLWfIsJO11kKdaAkOUHBEN5DKrXJ46Vs4918bD1/Q +6ztqdrThiKc646u9xB58Hg7F0IyMWbHfs0x16ZpcN9otrIkbqOE2wzTmc65O1t1i +HDljcSk7OnNy3a9wtLEnyPiyMqHf2k/bTlmiDRVe3cSy9xieoqmzHTnOCSASe1y9 +7lcEBQild18Jo4nACV4vCYOUwrMi/58LWW+lD6OmMnPiWUqOvMbgMffMNDpWPA== +-----END CERTIFICATE REQUEST----- diff --git a/tests/certs/valid/server/server.key b/tests/certs/valid/server/server.key new file mode 100644 index 0000000000..d6afaf59fe --- /dev/null +++ b/tests/certs/valid/server/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQChEKOx377ymuDg +23By5Re1DHi2RiBKSHr85/ZTZuwP/69lHN7qTQEO//EMEFZ9+ZwezeJJsejjP2HO +5lQZbcsWok3hbM0wVT+vApkogPvJ8WNFFWFeZBnGLi/1WM9cSZpUsDJ0XCsG0RTt +O27wfgZQlKQMZxTkfi971oPYxNVSjTm2JcLTkvwYIwxjJXPDTOgRo9TEAY3cWkCr +BJN4w74GWBTM5KDDA230T7WwLuv81XD2LvYjYYdMBGcxPr5tYTIlp3LncbcrDRNk +3pbYQk0bRJgkw2vUkteiRGjkt+dgVnLc6+MIW+VLXEpj+zsOZ5/R4d1pofqj9sDy +DPhtNr1JAgMBAAECggEAIuLzBfXgCvXzlBjL2kMXd7p4EgkN+PEKnKmUr/t40b1Q +zR6sBQWBX3GeET4fseElSQHQzCQaPNCve4xltm1S4jftFREHP7sTVHHEYWLQxuy/ +Uwkewj5927CI6ERgg82YfVP91bjaA/u5I+pt7O7rKLyNbPdN7fEMEW+FNuhpiVvg +JMrcK1BCFL6pmIT21LyTwkacMKZSPko58pWE24MA9aSCHk6cXdwQWQK0AfQT3XGT +C4I0hRed7LgqMH+gMuhpakiO13t8yTwxt2iQC9+aa4oSHD3BOi/CwIWfe1mHwmlr +cj4Kof1JSnK4SVTD16T++PlnWZkF6oaLUNg+/c2C9QKBgQDOFSYIY7+HzinT2hbI +yTIJCHpp+Iee+WVvvxjdZIPMDINrlIiHcMfXb0itUdcUO6tz0KYDMDLRC9CSP0ar +6mBWUTHfAKF2S4JpI9JYI4PNtIpOP1NiYuyJlnh5+ytU1yIeIvl39hmLcRwI9mgz +njy/D7yEoDCrG1dhcltubKpNXQKBgQDIFAVg0A7MNcxBZDLlk1NAME2JKOSszX8E +VNucvZD+9l+L9V9BmwwPQdzYifv/dNp3nYn+lxRPPgze3ZWu4+PeDuGudxu0I6ll +beFdbIcp1wbeQguzHYLjBYJqsMb4Pao5HPInjPu/HWfZlg9oZpJbKVucQwbonJLX +lgca9KaE3QKBgA+OUx+g/+0tZ8ThGoUvgsJhzHPBWeNrKfgEcckMdFJrw2PUg3XN +0pf1g4PpwJV7Z5bHcjCda8iR3r2bXydM+tapLF2L+6QlUQPEu3UBwUo+zY3Yg9/S +Xc6I+DEk/4FY9+9UboZaolT/RcF7cCQtVqKJeo58VRAlcTQe4L32H+jVAoGALXX3 +Ht9HbXkP1w/YTLej4+LVy0OCag0rPiW13LBqALSkUx3GrhZ3sAPMFVuM6ad4eFNQ +ZouXbsXvkLgSabGYNf11o/mmTtEHjWdhHKQrNgOIqPmixOkAs2quDmXqX79LLTz5 +fKkZDny0+wiQqa0cth/4k9HbAQGKj/ej16kdKPUCgYAz08Y39NnJYxRNz3tu/7C6 +jKyXKxhuZCZCt3cSWto5Tg0mVVB+2Jk2GhG1hCfZoRCP25R3FFBR1HOJgOc59T7C +LL67FdO0+7mj/WNzHj3+9gyOYQyQgPVDaTmsJLbuzT2S+GpR94ZNliwL2NEa5baG +B/Nb2ruRNj0GgZVw48N4XQ== +-----END PRIVATE KEY----- diff --git a/tests/certs/valid/server/server.pem b/tests/certs/valid/server/server.pem new file mode 100644 index 0000000000..0168cd3e3f --- /dev/null +++ b/tests/certs/valid/server/server.pem @@ -0,0 +1,47 @@ +-----BEGIN CERTIFICATE----- +MIIEhTCCA22gAwIBAgIUTzbDp+B1umRS0Q7rgefxif9Im3wwDQYJKoZIhvcNAQEL +BQAwajELMAkGA1UEBhMCVVMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3Vu +ZGF0aW9uMRgwFgYDVQQLDA9weXRob24tcmVxdWVzdHMxHDAaBgNVBAMME1NlbGYt +U2lnbmVkIFJvb3QgQ0EwHhcNMjQwMzE0MDAxMDAzWhcNNDMxMTMwMDAxMDAzWjBt +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCREUxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0 +d2FyZSBGb3VuZGF0aW9uMRgwFgYDVQQLDA9weXRob24tcmVxdWVzdHMxEjAQBgNV +BAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKEQ +o7HfvvKa4ODbcHLlF7UMeLZGIEpIevzn9lNm7A//r2Uc3upNAQ7/8QwQVn35nB7N +4kmx6OM/Yc7mVBltyxaiTeFszTBVP68CmSiA+8nxY0UVYV5kGcYuL/VYz1xJmlSw +MnRcKwbRFO07bvB+BlCUpAxnFOR+L3vWg9jE1VKNObYlwtOS/BgjDGMlc8NM6BGj +1MQBjdxaQKsEk3jDvgZYFMzkoMMDbfRPtbAu6/zVcPYu9iNhh0wEZzE+vm1hMiWn +cudxtysNE2TelthCTRtEmCTDa9SS16JEaOS352BWctzr4whb5UtcSmP7Ow5nn9Hh +3Wmh+qP2wPIM+G02vUkCAwEAAaOCAR4wggEaMAwGA1UdEwEB/wQCMAAwDgYDVR0P +AQH/BAQDAgWgMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMC8GA1UdEQEB/wQlMCOC +CWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATAdBgNVHQ4EFgQUJ90a +UnXKPP13yDprLhG39fUrnu8wgZEGA1UdIwSBiTCBhqFupGwwajELMAkGA1UEBhMC +VVMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRgwFgYDVQQL +DA9weXRob24tcmVxdWVzdHMxHDAaBgNVBAMME1NlbGYtU2lnbmVkIFJvb3QgQ0GC +FA9wdtNh/V99DRwYp8vXjPxSjJnWMA0GCSqGSIb3DQEBCwUAA4IBAQCVh4hiraRv +JzYbS/TombP//xfVEWHXDBEYsT5GgWf7GPJ/QtSvv6uJFsK7heqLzf9f+r4Z5xMh +YAkb0oe/Ge0T30Mo1YaBEqkKuQL9lOMcP69S9uFz2VT6I/76I8qqAu2AFhu74p8f +qudwmQyRYo1Ryg4R/SgRhSJKF/ST/2wOusNWSsBe1s8S2PmtOb4dr3cMBGihrUzS +DmCQpWjuiuE23HXnnYDc/EUAnEEPkLDgCsE9iLq37FPUHcHjqdYIAhmImPBpv2EL +ftXeRWfxN2hRHpS5Fn3QuAOwfJw5tUcVXojJCJfSpL+Ac97iSjxNaDIPlyomauKw +1rgbUkSw+9JQ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDWzCCAkMCFA9wdtNh/V99DRwYp8vXjPxSjJnWMA0GCSqGSIb3DQEBCwUAMGox +CzAJBgNVBAYTAlVTMSMwIQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlv +bjEYMBYGA1UECwwPcHl0aG9uLXJlcXVlc3RzMRwwGgYDVQQDDBNTZWxmLVNpZ25l +ZCBSb290IENBMB4XDTI0MDMxMjIxMDQwM1oXDTQ0MDMwNzIxMDQwM1owajELMAkG +A1UEBhMCVVMxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRgw +FgYDVQQLDA9weXRob24tcmVxdWVzdHMxHDAaBgNVBAMME1NlbGYtU2lnbmVkIFJv +b3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHlIhe7GLCeSk8 +RZOKdtmyKns6KdZgGw/LcxPkYvQlu1g0zV8X0DqVr2LdMumWUTNCc9sPdSlAG+He +mQp2TMoWUMumMuwDtit9RT0Sb6Eh9svWgjY9ferovPJRfCWUTsA2Ug8uoh0wyEXK +na7X6fHt5E3B9vj0+b9a4vDibdBXV11FheLT02/uEmAEJDdP/zeBgvVbhcVyumO6 +fAGMIWzR2ukhe8z/ma5H9zoi4gZA8nsK6reZUD8+6affnPe+jIt/AdzggtV9jkWm +zSpr+RHeZ0y+q4eik2ZNUGg4XcF6JsJ9yu/AqLBXxd38uLdFfgyhP2y6K628yzgy +e6lzFyWnAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGymNVTsKSAq8Ju6zV+AWAyV +GcUNBmLpgzDA0e7pkVYhHTdWKlGH4GnrRcp0nvnSbr6iq1Ob/8yEUUoRzK55Flws +Kt1OLwnZyhfRoSUesoEqpP68vzWEgiYv0QuIWvzNt0YfAAvEgGoc3iri44MelKLn +9ZMT8m91nVamA35R8ZjfeAkNp2xcz0a67V0ww6o4wSXrG7o5ZRXyjqZ/9K7SfwUJ +rV9RciccsjH/MzKbfrx73QwsbPWiFmjzHopdasIO0lDlmgm/r9gKfkbzfKoGCgLZ +6an6FlmLftLSXijf/QwtqeSP9fODeE3dzBmnTM3jdoVS53ZegUDWNl14o25v2Kg= +-----END CERTIFICATE----- diff --git a/tests/test_requests.py b/tests/test_requests.py index d5cc13c79f..4de47bc693 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -7,6 +7,7 @@ import os import pickle import re +import threading import warnings from unittest import mock @@ -51,6 +52,7 @@ from . import SNIMissingWarning from .compat import StringIO +from .testserver.server import TLSServer, consume_socket_content from .utils import override_environ # Requests to this URL should always fail with a connection timeout (nothing @@ -2828,12 +2830,140 @@ def test_status_code_425(self): assert r5 == 425 assert r6 == 425 - def test_different_connection_pool_for_tls_settings(self): + def test_different_connection_pool_for_tls_settings_verify_True(self): + def response_handler(sock): + consume_socket_content(sock, timeout=0.5) + sock.send( + b"HTTP/1.1 200 OK\r\n" + b"Content-Length: 18\r\n\r\n" + b'\xff\xfe{\x00"\x00K0"\x00=\x00"\x00\xab0"\x00\r\n' + ) + + s = requests.Session() + close_server = threading.Event() + server = TLSServer( + handler=response_handler, + wait_to_close_event=close_server, + requests_to_handle=3, + cert_chain="tests/certs/expired/server/server.pem", + keyfile="tests/certs/expired/server/server.key", + ) + + with server as (host, port): + url = f"https://{host}:{port}" + r1 = s.get(url, verify=False) + assert r1.status_code == 200 + + # Cannot verify self-signed certificate + with pytest.raises(requests.exceptions.SSLError): + s.get(url) + + close_server.set() + assert 2 == len(s.adapters["https://"].poolmanager.pools) + + def test_different_connection_pool_for_tls_settings_verify_bundle_expired_cert( + self, + ): + def response_handler(sock): + consume_socket_content(sock, timeout=0.5) + sock.send( + b"HTTP/1.1 200 OK\r\n" + b"Content-Length: 18\r\n\r\n" + b'\xff\xfe{\x00"\x00K0"\x00=\x00"\x00\xab0"\x00\r\n' + ) + + s = requests.Session() + close_server = threading.Event() + server = TLSServer( + handler=response_handler, + wait_to_close_event=close_server, + requests_to_handle=3, + cert_chain="tests/certs/expired/server/server.pem", + keyfile="tests/certs/expired/server/server.key", + ) + + with server as (host, port): + url = f"https://{host}:{port}" + r1 = s.get(url, verify=False) + assert r1.status_code == 200 + + # Has right trust bundle, but certificate expired + with pytest.raises(requests.exceptions.SSLError): + s.get(url, verify="tests/certs/expired/ca/ca.crt") + + close_server.set() + assert 2 == len(s.adapters["https://"].poolmanager.pools) + + def test_different_connection_pool_for_tls_settings_verify_bundle_unexpired_cert( + self, + ): + def response_handler(sock): + consume_socket_content(sock, timeout=0.5) + sock.send( + b"HTTP/1.1 200 OK\r\n" + b"Content-Length: 18\r\n\r\n" + b'\xff\xfe{\x00"\x00K0"\x00=\x00"\x00\xab0"\x00\r\n' + ) + + s = requests.Session() + close_server = threading.Event() + server = TLSServer( + handler=response_handler, + wait_to_close_event=close_server, + requests_to_handle=3, + cert_chain="tests/certs/valid/server/server.pem", + keyfile="tests/certs/valid/server/server.key", + ) + + with server as (host, port): + url = f"https://{host}:{port}" + r1 = s.get(url, verify=False) + assert r1.status_code == 200 + + r2 = s.get(url, verify="tests/certs/valid/ca/ca.crt") + assert r2.status_code == 200 + + close_server.set() + assert 2 == len(s.adapters["https://"].poolmanager.pools) + + def test_different_connection_pool_for_mtls_settings(self): + client_cert = None + + def response_handler(sock): + nonlocal client_cert + client_cert = sock.getpeercert() + consume_socket_content(sock, timeout=0.5) + sock.send( + b"HTTP/1.1 200 OK\r\n" + b"Content-Length: 18\r\n\r\n" + b'\xff\xfe{\x00"\x00K0"\x00=\x00"\x00\xab0"\x00\r\n' + ) + s = requests.Session() - r1 = s.get("https://invalid.badssl.com", verify=False) - assert r1.status_code == 421 - with pytest.raises(requests.exceptions.SSLError): - s.get("https://invalid.badssl.com") + close_server = threading.Event() + server = TLSServer( + handler=response_handler, + wait_to_close_event=close_server, + requests_to_handle=2, + cert_chain="tests/certs/expired/server/server.pem", + keyfile="tests/certs/expired/server/server.key", + mutual_tls=True, + cacert="tests/certs/expired/ca/ca.crt", + ) + + cert = ( + "tests/certs/mtls/client/client.pem", + "tests/certs/mtls/client/client.key", + ) + with server as (host, port): + url = f"https://{host}:{port}" + r1 = s.get(url, verify=False, cert=cert) + assert r1.status_code == 200 + with pytest.raises(requests.exceptions.SSLError): + s.get(url, cert=cert) + close_server.set() + + assert client_cert is not None def test_json_decode_errors_are_serializable_deserializable(): diff --git a/tests/testserver/server.py b/tests/testserver/server.py index 5936abdf8b..da1b65608e 100644 --- a/tests/testserver/server.py +++ b/tests/testserver/server.py @@ -1,5 +1,6 @@ import select import socket +import ssl import threading @@ -132,3 +133,44 @@ def __exit__(self, exc_type, exc_value, traceback): self._close_server_sock_ignore_errors() self.join() return False # allow exceptions to propagate + + +class TLSServer(Server): + def __init__( + self, + *, + handler=None, + host="localhost", + port=0, + requests_to_handle=1, + wait_to_close_event=None, + cert_chain=None, + keyfile=None, + mutual_tls=False, + cacert=None, + ): + super().__init__( + handler=handler, + host=host, + port=port, + requests_to_handle=requests_to_handle, + wait_to_close_event=wait_to_close_event, + ) + self.cert_chain = cert_chain + self.keyfile = keyfile + self.ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + self.ssl_context.load_cert_chain(self.cert_chain, keyfile=self.keyfile) + self.mutual_tls = mutual_tls + self.cacert = cacert + if mutual_tls: + # For simplicity, we're going to assume that the client cert is + # issued by the same CA as our Server certificate + self.ssl_context.verify_mode = ssl.CERT_OPTIONAL + self.ssl_context.load_verify_locations(self.cacert) + + def _create_socket_and_bind(self): + sock = socket.socket() + sock = self.ssl_context.wrap_socket(sock, server_side=True) + sock.bind((self.host, self.port)) + sock.listen() + return sock From 1604e20fc87ce212cf3a02474a6d7509b640cbbb Mon Sep 17 00:00:00 2001 From: flysee Date: Wed, 7 Dec 2022 11:24:22 +0000 Subject: [PATCH 74/88] Fix the proxy_bypass_registry function all returning true in some cases. --- src/requests/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/requests/utils.py b/src/requests/utils.py index a603a8638c..9067904563 100644 --- a/src/requests/utils.py +++ b/src/requests/utils.py @@ -97,6 +97,8 @@ def proxy_bypass_registry(host): # '' string by the localhost entry and the corresponding # canonical entry. proxyOverride = proxyOverride.split(";") + # filter out empty strings to avoid re.match all true. + proxyOverride = filter(None, proxyOverride) # now check if we match one of the registry values. for test in proxyOverride: if test == "": From 13d892bdbe9a2aa374959a166e8067c35253705d Mon Sep 17 00:00:00 2001 From: flysee Date: Mon, 18 Mar 2024 22:33:17 +0800 Subject: [PATCH 75/88] Additional should_bypass_proxies function test cases --- src/requests/utils.py | 2 +- tests/test_utils.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/requests/utils.py b/src/requests/utils.py index 9067904563..ae6c42f6cb 100644 --- a/src/requests/utils.py +++ b/src/requests/utils.py @@ -97,7 +97,7 @@ def proxy_bypass_registry(host): # '' string by the localhost entry and the corresponding # canonical entry. proxyOverride = proxyOverride.split(";") - # filter out empty strings to avoid re.match all true. + # filter out empty strings to avoid re.match return true in the following code. proxyOverride = filter(None, proxyOverride) # now check if we match one of the registry values. for test in proxyOverride: diff --git a/tests/test_utils.py b/tests/test_utils.py index 8988eaf69c..5e9b56ea64 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -924,3 +924,35 @@ def test_set_environ_raises_exception(): raise Exception("Expected exception") assert "Expected exception" in str(exception.value) + + +@pytest.mark.skipif(os.name != "nt", reason="Test only on Windows") +def test_should_bypass_proxies_win_registry_ProxyOverride_value(monkeypatch): + """Tests for function should_bypass_proxies to check if proxy + can be bypassed or not with Windows ProxyOverride registry value ending with a semicolon. + """ + import winreg + + class RegHandle: + def Close(self): + pass + + ie_settings = RegHandle() + + def OpenKey(key, subkey): + return ie_settings + + def QueryValueEx(key, value_name): + if key is ie_settings: + if value_name == "ProxyEnable": + return [1] + elif value_name == "ProxyOverride": + return [ + "192.168.*;127.0.0.1;localhost.localdomain;172.16.1.1;<-loopback>;" + ] + + monkeypatch.setenv("NO_PROXY", "") + monkeypatch.setenv("no_proxy", "") + monkeypatch.setattr(winreg, "OpenKey", OpenKey) + monkeypatch.setattr(winreg, "QueryValueEx", QueryValueEx) + assert should_bypass_proxies("http://example.com/", None) is False From 2daa7b52a78984ab5e66358052fc8dfe93e251bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:00:20 +0000 Subject: [PATCH 76/88] Bump actions/setup-python from 5.0.0 to 5.1.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/0a5c61591373683505ea898e09a3ea4f39ef2b9c...82c7e631bb3cdc910f68e0081d67478d79c6982d) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b35a32d13a..46a7862eac 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: Set up Python - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: python-version: "3.x" - name: Run pre-commit diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 3275080233..c955029bc0 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: python-version: ${{ matrix.python-version }} cache: 'pip' From e45b428960ff3927812fc9b555e2ac627ba95769 Mon Sep 17 00:00:00 2001 From: "Michiel W. Beijen" Date: Mon, 8 Apr 2024 21:47:12 +0200 Subject: [PATCH 77/88] Add rfc9110 HTTP status code names RFC 9110 _HTTP Semantics_ obsoletes some earlier RFCs which defined HTTP 1.1. It adds some status codes that were previously only used for WebDAV to HTTP _proper_ after making the names somewhat more generic. See https://www.rfc-editor.org/rfc/rfc9110.html#name-changes-from-rfc-7231 This commit adds the http status code names from that RFC. --- src/requests/status_codes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/requests/status_codes.py b/src/requests/status_codes.py index 235881224f..c7945a2f06 100644 --- a/src/requests/status_codes.py +++ b/src/requests/status_codes.py @@ -24,7 +24,7 @@ # Informational. 100: ("continue",), 101: ("switching_protocols",), - 102: ("processing",), + 102: ("processing", "early-hints"), 103: ("checkpoint",), 122: ("uri_too_long", "request_uri_too_long"), 200: ("ok", "okay", "all_ok", "all_okay", "all_good", "\\o/", "✓"), @@ -65,8 +65,8 @@ 410: ("gone",), 411: ("length_required",), 412: ("precondition_failed", "precondition"), - 413: ("request_entity_too_large",), - 414: ("request_uri_too_large",), + 413: ("request_entity_too_large", "content_too_large"), + 414: ("request_uri_too_large", "uri_too_long"), 415: ("unsupported_media_type", "unsupported_media", "media_type"), 416: ( "requested_range_not_satisfiable", @@ -76,7 +76,7 @@ 417: ("expectation_failed",), 418: ("im_a_teapot", "teapot", "i_am_a_teapot"), 421: ("misdirected_request",), - 422: ("unprocessable_entity", "unprocessable"), + 422: ("unprocessable_entity", "unprocessable", "unprocessable_content"), 423: ("locked",), 424: ("failed_dependency", "dependency"), 425: ("unordered_collection", "unordered", "too_early"), From cc23d1c6445d61c1e6905cae4861d6e3c3244274 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Thu, 11 Apr 2024 21:10:36 +0200 Subject: [PATCH 78/88] Fix compatibility with pytest 8 `pytest.warns(None)` has been deprecated in pytest 7.0.0 and it's no longer working in pytest 8. Resolves: https://github.com/psf/requests/issues/6679 --- requirements-dev.txt | 2 +- tests/test_requests.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 13173f3ae5..e80b18581e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,5 @@ -e .[socks] -pytest>=2.8.0,<=6.2.5 +pytest>=2.8.0,<9 pytest-cov pytest-httpbin==2.0.0 httpbin~=0.10.0 diff --git a/tests/test_requests.py b/tests/test_requests.py index 4de47bc693..d05febeef5 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1003,7 +1003,7 @@ def test_https_warnings(self, nosan_server): "SubjectAltNameWarning", ) - with pytest.warns(None) as warning_records: + with pytest.warns() as warning_records: warnings.simplefilter("always") requests.get(f"https://localhost:{port}/", verify=ca_bundle) From 60047ade64b0b882cbc94e047198818ab580911e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 16:40:35 +0000 Subject: [PATCH 79/88] Bump github/codeql-action from 3.24.0 to 3.25.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.0 to 3.25.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e8893c57a1f3a2b659b6b55564fdfdbbd2982911...df5a14dc28094dc936e103b37d749c6628682b60) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 26a4348a4b..b6d544640b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 + uses: github/codeql-action/init@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 with: languages: "python" # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 + uses: github/codeql-action/autobuild@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0 + uses: github/codeql-action/analyze@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 From 2d5f54779ad174035c5437b3b3c1146b0eaf60fe Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 23 Apr 2024 11:50:19 -0600 Subject: [PATCH 80/88] Pin 3.8 and 3.9 runners back to macos-13 (#6688) --- .github/workflows/run-tests.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c955029bc0..e1699fe81a 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -14,6 +14,15 @@ jobs: matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.9", "pypy-3.10"] os: [ubuntu-22.04, macOS-latest, windows-latest] + # Python 3.8 and 3.9 do not run on macOS-latest which + # is now using arm64 hardware. + # https://github.com/actions/setup-python/issues/696#issuecomment-1637587760 + exclude: + - { python-version: "3.8", os: "macos-latest" } + - { python-version: "3.9", os: "macos-latest" } + include: + - { python-version: "3.8", os: "macos-13" } + - { python-version: "3.9", os: "macos-13" } steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 From bf24b7d8d17da34be720c19e5978b2d3bf94a53b Mon Sep 17 00:00:00 2001 From: franekmagiera Date: Sun, 12 May 2024 22:08:24 +0200 Subject: [PATCH 81/88] Use an invalid URI that will not cause httpbin to throw 500 --- tests/test_requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_requests.py b/tests/test_requests.py index d05febeef5..b4e9fe92ae 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -2721,7 +2721,7 @@ def test_preparing_bad_url(self, url): with pytest.raises(requests.exceptions.InvalidURL): r.prepare() - @pytest.mark.parametrize("url, exception", (("http://localhost:-1", InvalidURL),)) + @pytest.mark.parametrize("url, exception", (("http://:1", InvalidURL),)) def test_redirecting_to_bad_url(self, httpbin, url, exception): with pytest.raises(exception): requests.get(httpbin("redirect-to"), params={"url": url}) From 555b870eb19d497ddb67042645420083ec8efb02 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 14 May 2024 14:59:26 -0700 Subject: [PATCH 82/88] Allow character detection dependencies to be optional in post-packaging steps --- .github/workflows/run-tests.yml | 20 ++++++++++++++++++++ src/requests/__init__.py | 6 +++++- src/requests/compat.py | 25 ++++++++++++++++++++----- src/requests/models.py | 7 ++++++- src/requests/packages.py | 25 +++++++++---------------- 5 files changed, 60 insertions(+), 23 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index e1699fe81a..c35af968c4 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -37,3 +37,23 @@ jobs: - name: Run tests run: | make ci + + no_chardet: + name: "No Character Detection" + runs-on: ubuntu-latest + strategy: + fail-fast: true + + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - name: 'Set up Python 3.8' + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d + with: + python-version: '3.8' + - name: Install dependencies + run: | + make + python -m pip uninstall -y "charset_normalizer" "chardet" + - name: Run tests + run: | + make ci diff --git a/src/requests/__init__.py b/src/requests/__init__.py index 300a16c574..051cda1340 100644 --- a/src/requests/__init__.py +++ b/src/requests/__init__.py @@ -83,7 +83,11 @@ def check_compatibility(urllib3_version, chardet_version, charset_normalizer_ver # charset_normalizer >= 2.0.0 < 4.0.0 assert (2, 0, 0) <= (major, minor, patch) < (4, 0, 0) else: - raise Exception("You need either charset_normalizer or chardet installed") + warnings.warn( + "Unable to find acceptable character detection dependency " + "(chardet or charset_normalizer).", + RequestsDependencyWarning, + ) def _check_cryptography(cryptography_version): diff --git a/src/requests/compat.py b/src/requests/compat.py index 6776163c94..095de1b6ca 100644 --- a/src/requests/compat.py +++ b/src/requests/compat.py @@ -7,13 +7,28 @@ compatibility until the next major version. """ -try: - import chardet -except ImportError: - import charset_normalizer as chardet - +import importlib import sys +# ------------------- +# Character Detection +# ------------------- + + +def _resolve_char_detection(): + """Find supported character detection libraries.""" + chardet = None + for lib in ("chardet", "charset_normalizer"): + if chardet is None: + try: + chardet = importlib.import_module(lib) + except ImportError: + pass + return chardet + + +chardet = _resolve_char_detection() + # ------- # Pythons # ------- diff --git a/src/requests/models.py b/src/requests/models.py index 44556394ec..8f56ca7d23 100644 --- a/src/requests/models.py +++ b/src/requests/models.py @@ -789,7 +789,12 @@ def next(self): @property def apparent_encoding(self): """The apparent encoding, provided by the charset_normalizer or chardet libraries.""" - return chardet.detect(self.content)["encoding"] + if chardet is not None: + return chardet.detect(self.content)["encoding"] + else: + # If no character detection library is available, we'll fall back + # to a standard Python utf-8 str. + return "utf-8" def iter_content(self, chunk_size=1, decode_unicode=False): """Iterates over the response data. When stream=True is set on the diff --git a/src/requests/packages.py b/src/requests/packages.py index a9e5ae087d..5ab3d8e250 100644 --- a/src/requests/packages.py +++ b/src/requests/packages.py @@ -1,13 +1,6 @@ import sys -try: - import chardet -except ImportError: - import warnings - - import charset_normalizer as chardet - - warnings.filterwarnings("ignore", "Trying to detect", module="charset_normalizer") +from .compat import chardet # This code exists for backwards compatibility reasons. # I don't like it either. Just look the other way. :) @@ -20,11 +13,11 @@ if mod == package or mod.startswith(f"{package}."): sys.modules[f"requests.packages.{mod}"] = sys.modules[mod] -target = chardet.__name__ -for mod in list(sys.modules): - if mod == target or mod.startswith(f"{target}."): - imported_mod = sys.modules[mod] - sys.modules[f"requests.packages.{mod}"] = imported_mod - mod = mod.replace(target, "chardet") - sys.modules[f"requests.packages.{mod}"] = imported_mod -# Kinda cool, though, right? +if chardet is not None: + target = chardet.__name__ + for mod in list(sys.modules): + if mod == target or mod.startswith(f"{target}."): + imported_mod = sys.modules[mod] + sys.modules[f"requests.packages.{mod}"] = imported_mod + mod = mod.replace(target, "chardet") + sys.modules[f"requests.packages.{mod}"] = imported_mod From 9a40d1277807f0a4f26c9a37eea8ec90faa8aadc Mon Sep 17 00:00:00 2001 From: agubelu Date: Wed, 15 May 2024 22:07:26 +0200 Subject: [PATCH 83/88] Avoid reloading root certificates to improve concurrent performance (#6667) --- src/requests/adapters.py | 46 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/requests/adapters.py b/src/requests/adapters.py index 84ec48fc70..f544f9d545 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -26,6 +26,7 @@ from urllib3.util import Timeout as TimeoutSauce from urllib3.util import parse_url from urllib3.util.retry import Retry +from urllib3.util.ssl_ import create_urllib3_context from .auth import _basic_auth_str from .compat import basestring, urlparse @@ -71,6 +72,11 @@ def SOCKSProxyManager(*args, **kwargs): DEFAULT_RETRIES = 0 DEFAULT_POOL_TIMEOUT = None +_preloaded_ssl_context = create_urllib3_context() +_preloaded_ssl_context.load_verify_locations( + extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) +) + def _urllib3_request_context( request: "PreparedRequest", @@ -85,8 +91,13 @@ def _urllib3_request_context( cert_reqs = "CERT_REQUIRED" if verify is False: cert_reqs = "CERT_NONE" - if isinstance(verify, str): - pool_kwargs["ca_certs"] = verify + elif verify is True: + pool_kwargs["ssl_context"] = _preloaded_ssl_context + elif isinstance(verify, str): + if not os.path.isdir(verify): + pool_kwargs["ca_certs"] = verify + else: + pool_kwargs["ca_cert_dir"] = verify pool_kwargs["cert_reqs"] = cert_reqs if client_cert is not None: if isinstance(client_cert, tuple) and len(client_cert) == 2: @@ -284,27 +295,26 @@ def cert_verify(self, conn, url, verify, cert): :param cert: The SSL certificate to verify. """ if url.lower().startswith("https") and verify: - cert_loc = None + conn.cert_reqs = "CERT_REQUIRED" - # Allow self-specified cert location. + # Only load the CA certificates if 'verify' is a string indicating the CA bundle to use. + # Otherwise, if verify is a boolean, we don't load anything since + # the connection will be using a context with the default certificates already loaded, + # and this avoids a call to the slow load_verify_locations() if verify is not True: + # `verify` must be a str with a path then cert_loc = verify - if not cert_loc: - cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) - - if not cert_loc or not os.path.exists(cert_loc): - raise OSError( - f"Could not find a suitable TLS CA certificate bundle, " - f"invalid path: {cert_loc}" - ) + if not os.path.exists(cert_loc): + raise OSError( + f"Could not find a suitable TLS CA certificate bundle, " + f"invalid path: {cert_loc}" + ) - conn.cert_reqs = "CERT_REQUIRED" - - if not os.path.isdir(cert_loc): - conn.ca_certs = cert_loc - else: - conn.ca_cert_dir = cert_loc + if not os.path.isdir(cert_loc): + conn.ca_certs = cert_loc + else: + conn.ca_cert_dir = cert_loc else: conn.cert_reqs = "CERT_NONE" conn.ca_certs = None From d6ebc4a2f1f68b7e355fb7e4dd5ffc0845547f9f Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Mon, 20 May 2024 08:46:49 -0700 Subject: [PATCH 84/88] v2.32.0 --- HISTORY.md | 46 +++++++++++++++++++++++++++++++++++++ src/requests/__version__.py | 4 ++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 432ee3b174..7c2cd71c10 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,52 @@ dev - \[Short description of non-trivial change.\] +2.32.0 (2024-05-20) +------------------- + +**Security** +- Fixed an issue where setting `verify=False` on the first request from a + Session will cause subsequent requests to the _same origin_ to also ignore + cert verification, regardless of the value of `verify`. + (https://github.com/psf/requests/security/advisories/GHSA-9wx4-h78v-vm56) + +**Improvements** +- `verify=True` now reuses a global SSLContext which should improve + request time variance between first and subsequent requests. It should + also minimize certificate load time on Windows systems when using a Python + version built with OpenSSL 3.x. (#6667) +- Requests now supports optional use of character detection + (`chardet` or `charset_normalizer`) when repackaged or vendored. + This enables `pip` and other projects to minimize their vendoring + surface area. The `Response.text()` and `apparent_encoding` APIs + will default to `utf-8` if neither library is present. (#6702) + +**Bugfixes** +- Fixed bug in length detection where emoji length was incorrectly + calculated in the request content-length. (#6589) +- Fixed deserialization bug in JSONDecodeError. (#6629) +- Fixed bug where an extra leading `/` (path separator) could lead + urllib3 to unnecessarily reparse the request URI. (#6644) + +**Deprecations** + +- Requests has officially added support for CPython 3.12 (#6503) +- Requests has officially added support for PyPy 3.9 and 3.10 (#6641) +- Requests has officially dropped support for CPython 3.7 (#6642) +- Requests has officially dropped support for PyPy 3.7 and 3.8 (#6641) + +**Documentation** +- Various typo fixes and doc improvements. + +**Packaging** +- Requests has started adopting some modern packaging practices. + The source files for the projects (formerly `requests`) is now located + in `src/requests` in the Requests sdist. (#6506) +- Starting in Requests 2.33.0, Requests will migrate to a PEP 517 build system + using `hatchling`. This should not impact the average user, but extremely old + versions of packaging utilities may have issues with the new packaging format. + + 2.31.0 (2023-05-22) ------------------- diff --git a/src/requests/__version__.py b/src/requests/__version__.py index d206427e50..1ac168734e 100644 --- a/src/requests/__version__.py +++ b/src/requests/__version__.py @@ -5,8 +5,8 @@ __title__ = "requests" __description__ = "Python HTTP for Humans." __url__ = "https://requests.readthedocs.io" -__version__ = "2.31.0" -__build__ = 0x023100 +__version__ = "2.32.0" +__build__ = 0x023200 __author__ = "Kenneth Reitz" __author_email__ = "me@kennethreitz.org" __license__ = "Apache-2.0" From 970e8cec988421bd43da57350723b05c8ce8dc7e Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Mon, 20 May 2024 15:02:29 -0700 Subject: [PATCH 85/88] v2.32.1 --- HISTORY.md | 7 +++++++ MANIFEST.in | 1 + src/requests/__version__.py | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7c2cd71c10..5ee5029d9f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,13 @@ dev - \[Short description of non-trivial change.\] +2.32.1 (2024-05-20) +------------------- + +**Bugfixes** +- Add missing test certs to the sdist distributed on PyPI. + + 2.32.0 (2024-05-20) ------------------- diff --git a/MANIFEST.in b/MANIFEST.in index 87a23ab937..9dd81e6f0f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,3 @@ include README.md LICENSE NOTICE HISTORY.md requirements-dev.txt recursive-include tests *.py +recursive-include tests/certs * diff --git a/src/requests/__version__.py b/src/requests/__version__.py index 1ac168734e..ecc87fbf72 100644 --- a/src/requests/__version__.py +++ b/src/requests/__version__.py @@ -5,8 +5,8 @@ __title__ = "requests" __description__ = "Python HTTP for Humans." __url__ = "https://requests.readthedocs.io" -__version__ = "2.32.0" -__build__ = 0x023200 +__version__ = "2.32.1" +__build__ = 0x023201 __author__ = "Kenneth Reitz" __author_email__ = "me@kennethreitz.org" __license__ = "Apache-2.0" From aa1461b68aa73e2f6ec0e78c8853b635c76fd099 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 21 May 2024 05:40:52 -0700 Subject: [PATCH 86/88] Move _get_connection to get_connection_with_tls_context --- src/requests/adapters.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/requests/adapters.py b/src/requests/adapters.py index f544f9d545..3c9ddebfcc 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -374,10 +374,20 @@ def build_response(self, req, resp): return response - def _get_connection(self, request, verify, proxies=None, cert=None): - # Replace the existing get_connection without breaking things and - # ensure that TLS settings are considered when we interact with - # urllib3 HTTP Pools + def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None): + """Returns a urllib3 connection for the given request and TLS settings. + This should not be called from user code, and is only exposed for use + when subclassing the :class:`HTTPAdapter `. + + :param request: The :class:`PreparedRequest ` object + to be sent over the connection. + :param verify: Either a boolean, in which case it controls whether + we verify the server's TLS certificate, or a string, in which case it + must be a path to a CA bundle to use. + :param proxies: (optional) The proxies dictionary to apply to the request. + :param cert: (optional) Any user-provided SSL certificate to be trusted. + :rtype: urllib3.ConnectionPool + """ proxy = select_proxy(request.url, proxies) try: host_params, pool_kwargs = _urllib3_request_context(request, verify, cert) @@ -404,7 +414,10 @@ def _get_connection(self, request, verify, proxies=None, cert=None): return conn def get_connection(self, url, proxies=None): - """Returns a urllib3 connection for the given URL. This should not be + """DEPRECATED: Users should move to `get_connection_with_tls_context` + for all subclasses of HTTPAdapter using Requests>=2.32.2. + + Returns a urllib3 connection for the given URL. This should not be called from user code, and is only exposed for use when subclassing the :class:`HTTPAdapter `. @@ -529,7 +542,9 @@ def send( """ try: - conn = self._get_connection(request, verify, proxies=proxies, cert=cert) + conn = self.get_connection_with_tls_context( + request, verify, proxies=proxies, cert=cert + ) except LocationValueError as e: raise InvalidURL(e, request=request) From 92075b330a30b9883f466a43d3f7566ab849f91b Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 21 May 2024 09:28:30 -0700 Subject: [PATCH 87/88] Add deprecation warning --- src/requests/adapters.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/requests/adapters.py b/src/requests/adapters.py index 3c9ddebfcc..42fabe527c 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -9,6 +9,7 @@ import os.path import socket # noqa: F401 import typing +import warnings from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError from urllib3.exceptions import HTTPError as _HTTPError @@ -425,6 +426,15 @@ def get_connection(self, url, proxies=None): :param proxies: (optional) A Requests-style dictionary of proxies used on this request. :rtype: urllib3.ConnectionPool """ + warnings.warn( + ( + "`get_connection` has been deprecated in favor of " + "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses " + "will need to migrate for Requests>=2.32.2. Please see " + "https://github.com/psf/requests/pull/6710 for more details." + ), + DeprecationWarning, + ) proxy = select_proxy(url, proxies) if proxy: From 88dce9d854797c05d0ff296b70e0430535ef8aaf Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Tue, 21 May 2024 11:49:22 -0700 Subject: [PATCH 88/88] v2.32.2 --- HISTORY.md | 14 ++++++++++++++ src/requests/__version__.py | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 5ee5029d9f..4fca5894d7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,20 @@ dev - \[Short description of non-trivial change.\] +2.32.2 (2024-05-21) +------------------- + +**Deprecations** +- To provide a more stable migration for custom HTTPAdapters impacted + by the CVE changes in 2.32.0, we've renamed `_get_connection` to + a new public API, `get_connection_with_tls_context`. Existing custom + HTTPAdapters will need to migrate their code to use this new API. + `get_connection` is considered deprecated in all versions of Requests>=2.32.0. + + A minimal (2-line) example has been provided in the linked PR to ease + migration, but we strongly urge users to evaluate if their custom adapter + is subject to the same issue described in CVE-2024-35195. (#6710) + 2.32.1 (2024-05-20) ------------------- diff --git a/src/requests/__version__.py b/src/requests/__version__.py index ecc87fbf72..24829c4b5f 100644 --- a/src/requests/__version__.py +++ b/src/requests/__version__.py @@ -5,8 +5,8 @@ __title__ = "requests" __description__ = "Python HTTP for Humans." __url__ = "https://requests.readthedocs.io" -__version__ = "2.32.1" -__build__ = 0x023201 +__version__ = "2.32.2" +__build__ = 0x023202 __author__ = "Kenneth Reitz" __author_email__ = "me@kennethreitz.org" __license__ = "Apache-2.0"