Skip to content

Commit

Permalink
Merge pull request #5391 from hodbn/fix-5274
Browse files Browse the repository at this point in the history
Send only one Host header in chunked request
  • Loading branch information
nateprewitt committed Nov 29, 2021
2 parents 2d2447e + 4ab2550 commit 7556ea4
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS.rst
Expand Up @@ -191,3 +191,4 @@ Patches and Suggestions
- "Dull Bananas" <dull.bananas0@gmail.com> (`@dullbananas <https://github.com/dullbananas>`_)
- Alessio Izzo (`@aless10 <https://github.com/aless10>`_)
- Sylvain Marié (`@smarie <https://github.com/smarie>`_)
- Hod Bin Noon (`@hodbn <https://github.com/hodbn>`_)
4 changes: 3 additions & 1 deletion requests/adapters.py
Expand Up @@ -458,9 +458,11 @@ def send(self, request, stream=False, timeout=None, verify=True, cert=None, prox
low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT)

try:
skip_host = 'Host' in request.headers
low_conn.putrequest(request.method,
url,
skip_accept_encoding=True)
skip_accept_encoding=True,
skip_host=skip_host)

for header, value in request.headers.items():
low_conn.putheader(header, value)
Expand Down
48 changes: 48 additions & 0 deletions tests/test_lowlevel.py
Expand Up @@ -9,6 +9,18 @@
from .utils import override_environ


def echo_response_handler(sock):
"""Simple handler that will take request and echo it back to requester."""
request_content = consume_socket_content(sock, timeout=0.5)

text_200 = (
b'HTTP/1.1 200 OK\r\n'
b'Content-Length: %d\r\n\r\n'
b'%s'
) % (len(request_content), request_content)
sock.send(text_200)


def test_chunked_upload():
"""can safely send generators"""
close_server = threading.Event()
Expand Down Expand Up @@ -46,6 +58,42 @@ def incomplete_chunked_response_handler(sock):
close_server.set() # release server block


def test_chunked_upload_uses_only_specified_host_header():
"""Ensure we use only the specified Host header for chunked requests."""
close_server = threading.Event()
server = Server(echo_response_handler, wait_to_close_event=close_server)

data = iter([b'a', b'b', b'c'])
custom_host = 'sample-host'

with server as (host, port):
url = 'http://{}:{}/'.format(host, port)
r = requests.post(url, data=data, headers={'Host': custom_host}, stream=True)
close_server.set() # release server block

expected_header = b'Host: %s\r\n' % custom_host.encode('utf-8')
assert expected_header in r.content
assert r.content.count(b'Host: ') == 1


def test_chunked_upload_doesnt_skip_host_header():
"""Ensure we don't omit all Host headers with chunked requests."""
close_server = threading.Event()
server = Server(echo_response_handler, wait_to_close_event=close_server)

data = iter([b'a', b'b', b'c'])

with server as (host, port):
expected_host = '{}:{}'.format(host, port)
url = 'http://{}:{}/'.format(host, port)
r = requests.post(url, data=data, stream=True)
close_server.set() # release server block

expected_header = b'Host: %s\r\n' % expected_host.encode('utf-8')
assert expected_header in r.content
assert r.content.count(b'Host: ') == 1


def test_conflicting_content_lengths():
"""Ensure we correctly throw an InvalidHeader error if multiple
conflicting Content-Length headers are returned.
Expand Down

0 comments on commit 7556ea4

Please sign in to comment.