From 2d30aeb7c6d7180b67e2bb01962f3383739a1c62 Mon Sep 17 00:00:00 2001 From: Ben Li-Sauerwine Date: Tue, 24 Aug 2021 22:00:17 -0400 Subject: [PATCH 1/8] Add a test which verifies that ChunkedEncodingError is emitted if an invalid Transfer-Encoding: chunked response is returned. (#5906) --- tests/test_lowlevel.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py index 4127fb115e..d0fa136a69 100644 --- a/tests/test_lowlevel.py +++ b/tests/test_lowlevel.py @@ -24,6 +24,28 @@ def test_chunked_upload(): assert r.request.headers['Transfer-Encoding'] == 'chunked' +def test_chunked_encoding_error(): + """get a ChunkedEncodingError if the server returns a bad response""" + + def incomplete_chunked_response_handler(sock): + request_content = consume_socket_content(sock, timeout=0.5) + + # The server never ends the request and doesn't provide any valid chunks + sock.send(b"HTTP/1.1 200 OK\r\n" + + b"Transfer-Encoding: chunked\r\n") + + return request_content + + close_server = threading.Event() + server = Server(incomplete_chunked_response_handler) + + with server as (host, port): + url = 'http://{}:{}/'.format(host, port) + with pytest.raises(requests.exceptions.ChunkedEncodingError): + r = requests.get(url) + close_server.set() # release server block + + def test_digestauth_401_count_reset_on_redirect(): """Ensure we correctly reset num_401_calls after a successful digest auth, followed by a 302 redirect to another digest auth prompt. From 827b87b9bee88793051b6c7bb6639bb6d72a0654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D1=80=D0=B8=D1=81=20=D0=92=D0=B5=D1=80=D1=85?= =?UTF-8?q?=D0=BE=D0=B2=D1=81=D0=BA=D0=B8=D0=B9?= Date: Wed, 25 Aug 2021 12:48:30 -0400 Subject: [PATCH 2/8] Formatting (#5910) --- docs/user/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst index 73d0b2931a..4e70af957c 100644 --- a/docs/user/quickstart.rst +++ b/docs/user/quickstart.rst @@ -37,12 +37,12 @@ get all the information we need from this object. Requests' simple API means that all forms of HTTP request are as obvious. For example, this is how you make an HTTP POST request:: - >>> r = requests.post('https://httpbin.org/post', data = {'key':'value'}) + >>> r = requests.post('https://httpbin.org/post', data={'key': 'value'}) Nice, right? What about the other HTTP request types: PUT, DELETE, HEAD and OPTIONS? These are all just as simple:: - >>> r = requests.put('https://httpbin.org/put', data = {'key':'value'}) + >>> r = requests.put('https://httpbin.org/put', data={'key': 'value'}) >>> r = requests.delete('https://httpbin.org/delete') >>> r = requests.head('https://httpbin.org/get') >>> r = requests.options('https://httpbin.org/get') From 7adb8686ac011d2172a47d2e777ee1d9b5b9907b Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 25 Aug 2021 13:21:35 -0500 Subject: [PATCH 3/8] Add thread locker workflow (#5909) --- .github/workflows/lock-issues.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/lock-issues.yml diff --git a/.github/workflows/lock-issues.yml b/.github/workflows/lock-issues.yml new file mode 100644 index 0000000000..a88c64c6b7 --- /dev/null +++ b/.github/workflows/lock-issues.yml @@ -0,0 +1,15 @@ +name: 'Lock Threads' + +on: + schedule: + - cron: '0 0 * * *' + +permissions: + issues: write + pull-requests: write + +jobs: + action: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v2 From 8ea90a5ce7b085449a2b5c61743574bf911733ee Mon Sep 17 00:00:00 2001 From: Ian Stapleton Cordasco Date: Wed, 25 Aug 2021 13:23:34 -0500 Subject: [PATCH 4/8] Shorten the window before we lock threads Per Nate's recommendation, let's lock things after 90 days rather than 360 --- .github/workflows/lock-issues.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/lock-issues.yml b/.github/workflows/lock-issues.yml index a88c64c6b7..788fe83b74 100644 --- a/.github/workflows/lock-issues.yml +++ b/.github/workflows/lock-issues.yml @@ -13,3 +13,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: dessant/lock-threads@v2 + issue-lock-inactive-days: 90 + pr-lock-inactive-days: 90 From 70a13e2a263983ac3a3e93591e8cebcf8a2169b1 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Wed, 25 Aug 2021 18:04:43 -0700 Subject: [PATCH 5/8] Fix syntax error in lock action (#5912) --- .github/workflows/lock-issues.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lock-issues.yml b/.github/workflows/lock-issues.yml index 788fe83b74..d4a9e6478b 100644 --- a/.github/workflows/lock-issues.yml +++ b/.github/workflows/lock-issues.yml @@ -13,5 +13,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: dessant/lock-threads@v2 - issue-lock-inactive-days: 90 - pr-lock-inactive-days: 90 + with: + issue-lock-inactive-days: 90 + pr-lock-inactive-days: 90 From b351e906b62083b1dcfdb7a6c8aa8a4d3fb55ff4 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Thu, 26 Aug 2021 03:58:35 -0700 Subject: [PATCH 6/8] Update codeql branch target (#5913) --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index bf1463909c..cc5fd29dd3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -7,10 +7,10 @@ name: "CodeQL" on: push: - branches: [master] + branches: [main] pull_request: # The branches below must be a subset of the branches above - branches: [master] + branches: [main] schedule: - cron: '0 23 * * 0' From 10968357a19a146332c8dfd8e6d17006d746e580 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Thu, 26 Aug 2021 18:11:30 -0700 Subject: [PATCH 7/8] Appropriately handle urllib3's InvalidHeader exception (#5914) --- requests/adapters.py | 5 ++++- tests/test_lowlevel.py | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/requests/adapters.py b/requests/adapters.py index fa4d9b3cc9..9b7f92af66 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -19,6 +19,7 @@ from urllib3.exceptions import ClosedPoolError from urllib3.exceptions import ConnectTimeoutError from urllib3.exceptions import HTTPError as _HTTPError +from urllib3.exceptions import InvalidHeader as _InvalidHeader from urllib3.exceptions import MaxRetryError from urllib3.exceptions import NewConnectionError from urllib3.exceptions import ProxyError as _ProxyError @@ -37,7 +38,7 @@ from .cookies import extract_cookies_to_jar from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError, ProxyError, RetryError, InvalidSchema, InvalidProxyURL, - InvalidURL) + InvalidURL, InvalidHeader) from .auth import _basic_auth_str try: @@ -527,6 +528,8 @@ def send(self, request, stream=False, timeout=None, verify=True, cert=None, prox raise SSLError(e, request=request) elif isinstance(e, ReadTimeoutError): raise ReadTimeout(e, request=request) + elif isinstance(e, _InvalidHeader): + raise InvalidHeader(e, request=request) else: raise diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py index d0fa136a69..2ada004a74 100644 --- a/tests/test_lowlevel.py +++ b/tests/test_lowlevel.py @@ -46,6 +46,32 @@ def incomplete_chunked_response_handler(sock): close_server.set() # release server block +def test_conflicting_content_lengths(): + """Ensure we correctly throw an InvalidHeader error if multiple + conflicting Content-Length headers are returned. + """ + + def multiple_content_length_response_handler(sock): + request_content = consume_socket_content(sock, timeout=0.5) + + sock.send(b"HTTP/1.1 200 OK\r\n" + + b"Content-Type: text/plain\r\n" + + b"Content-Length: 16\r\n" + + b"Content-Length: 32\r\n\r\n" + + b"-- Bad Actor -- Original Content\r\n") + + return request_content + + close_server = threading.Event() + server = Server(multiple_content_length_response_handler) + + with server as (host, port): + url = 'http://{}:{}/'.format(host, port) + with pytest.raises(requests.exceptions.InvalidHeader): + r = requests.get(url) + close_server.set() + + def test_digestauth_401_count_reset_on_redirect(): """Ensure we correctly reset num_401_calls after a successful digest auth, followed by a 302 redirect to another digest auth prompt. From aae78010e987a414c176bddbf474cd554505219c Mon Sep 17 00:00:00 2001 From: Ben Li-Sauerwine Date: Fri, 27 Aug 2021 14:49:51 -0400 Subject: [PATCH 8/8] Time out requests' tests after 10 minutes. (#5916) --- .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 cf5f0b4b91..b8e90c78c7 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: build: runs-on: ${{ matrix.os }} - + timeout-minutes: 10 strategy: fail-fast: false matrix: