mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
#23539: Set Content-Length to 0 for PUT, POST, and PATCH if body is None.
Some http servers will reject PUT, POST, and PATCH requests if they do not have a Content-Length header. Patch by James Rutherford, with additional cleaning up of the 'request' documentation by me.
This commit is contained in:
parent
75ed90a4cf
commit
beed8402ca
5 changed files with 104 additions and 39 deletions
|
@ -246,6 +246,10 @@ _MAXHEADERS = 100
|
|||
_is_legal_header_name = re.compile(rb'[^:\s][^:\r\n]*').fullmatch
|
||||
_is_illegal_header_value = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])').search
|
||||
|
||||
# We always set the Content-Length header for these methods because some
|
||||
# servers will otherwise respond with a 411
|
||||
_METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'}
|
||||
|
||||
|
||||
class HTTPMessage(email.message.Message):
|
||||
# XXX The only usage of this method is in
|
||||
|
@ -1126,19 +1130,26 @@ class HTTPConnection:
|
|||
"""Send a complete request to the server."""
|
||||
self._send_request(method, url, body, headers)
|
||||
|
||||
def _set_content_length(self, body):
|
||||
# Set the content-length based on the body.
|
||||
def _set_content_length(self, body, method):
|
||||
# Set the content-length based on the body. If the body is "empty", we
|
||||
# set Content-Length: 0 for methods that expect a body (RFC 7230,
|
||||
# Section 3.3.2). If the body is set for other methods, we set the
|
||||
# header provided we can figure out what the length is.
|
||||
thelen = None
|
||||
try:
|
||||
thelen = str(len(body))
|
||||
except TypeError as te:
|
||||
# If this is a file-like object, try to
|
||||
# fstat its file descriptor
|
||||
method_expects_body = method.upper() in _METHODS_EXPECTING_BODY
|
||||
if body is None and method_expects_body:
|
||||
thelen = '0'
|
||||
elif body is not None:
|
||||
try:
|
||||
thelen = str(os.fstat(body.fileno()).st_size)
|
||||
except (AttributeError, OSError):
|
||||
# Don't send a length if this failed
|
||||
if self.debuglevel > 0: print("Cannot stat!!")
|
||||
thelen = str(len(body))
|
||||
except TypeError:
|
||||
# If this is a file-like object, try to
|
||||
# fstat its file descriptor
|
||||
try:
|
||||
thelen = str(os.fstat(body.fileno()).st_size)
|
||||
except (AttributeError, OSError):
|
||||
# Don't send a length if this failed
|
||||
if self.debuglevel > 0: print("Cannot stat!!")
|
||||
|
||||
if thelen is not None:
|
||||
self.putheader('Content-Length', thelen)
|
||||
|
@ -1154,8 +1165,8 @@ class HTTPConnection:
|
|||
|
||||
self.putrequest(method, url, **skips)
|
||||
|
||||
if body is not None and ('content-length' not in header_names):
|
||||
self._set_content_length(body)
|
||||
if 'content-length' not in header_names:
|
||||
self._set_content_length(body, method)
|
||||
for hdr, value in headers.items():
|
||||
self.putheader(hdr, value)
|
||||
if isinstance(body, str):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue