Fix empty encoded body sending spurious chunked terminator#7215
Open
danielalanbates wants to merge 1 commit intopsf:mainfrom
Open
Fix empty encoded body sending spurious chunked terminator#7215danielalanbates wants to merge 1 commit intopsf:mainfrom
danielalanbates wants to merge 1 commit intopsf:mainfrom
Conversation
When `data` encodes to an empty string (e.g. `data={'foo': None}`),
`prepare_body` set `body = ''` rather than `body = None`. This caused
`prepare_content_length` to skip setting `Content-Length: 0` (since
`super_len('')` is 0, which is falsy), and the adapter then treated the
request as chunked, sending a bare `0\r\n\r\n` terminator that servers
like nginx and Apache interpreted as a malformed second request.
The fix converts an empty encoded body to `None` so that
`prepare_content_length` correctly handles it: setting
`Content-Length: 0` for POST/PUT and omitting it for GET/HEAD.
Fixes psf#6122
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Daniel Bates <danielalanbates@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When
dataencodes to an empty string (e.g.data={'foo': None}ordata=[('a', None)]),prepare_bodypreviously setbody = ''rather thanbody = None. This causedprepare_content_lengthto skip settingContent-Length: 0(sincesuper_len('')returns0, which is falsy), and the adapter then treated the request as chunked, sending a bare0\r\n\r\nterminator that servers like nginx and Apache interpreted as a malformed second request — resulting in a 400 Bad Request.Root cause: In
models.py,self._encode_params(data)returned''(empty string) for data with all-None values. The empty string is truthy enough to bypass thebody is not Nonecheck inprepare_content_length, butsuper_len('')returns0which is falsy, so noContent-Lengthheader was set. WithoutContent-LengthorTransfer-Encoding, the adapter fell through to chunked encoding and sentb'0\r\n\r\n'.Fix: Convert an empty encoded body to
None(body = self._encode_params(data) or None) so thatprepare_content_lengthcorrectly handles it:Content-Length: 0Content-Lengthentirely (per RFC 7230 3.3.2)This is the minimal fix suggested by @nateprewitt in the original discussion.
Changes
src/requests/models.py: One-line change on the_encode_paramscalltests/test_lowlevel.py: Parametrized test covering both GET (no Content-Length) and POST (Content-Length: 0) with empty form data, verifying no chunked terminator is sentTest plan
test_empty_urlencoded_form_bodypasses for both GET and POSTtest_lowlevel.pytests pass (14/14)Request('POST', url, data={'foo': None}).prepare()now hasContent-Length: 0andbody is Nonedata={'foo': 'bar'}still works correctlyCloses #6122
This PR was created with the assistance of Claude Opus 4.6 by Anthropic. Happy to make any adjustments! Reviewed and submitted by a human.