summaryrefslogtreecommitdiffstats
path: root/Lib/http/client.py
diff options
context:
space:
mode:
authorR David Murray <rdmurray@bitdance.com>2015-03-22 19:19:01 (GMT)
committerR David Murray <rdmurray@bitdance.com>2015-03-22 19:19:01 (GMT)
commit0a0d20edfb19934cd3929d6c115ba31c00744a24 (patch)
tree3d94aed8ac2578a62e934b862dad95f08acc26eb /Lib/http/client.py
parent5d06c74f41a976cd042bfbb52f2f6762a44e1e26 (diff)
parentbeed8402ca2b44681f939238c8ea02deeb8a06a2 (diff)
downloadcpython-0a0d20edfb19934cd3929d6c115ba31c00744a24.zip
cpython-0a0d20edfb19934cd3929d6c115ba31c00744a24.tar.gz
cpython-0a0d20edfb19934cd3929d6c115ba31c00744a24.tar.bz2
Merge: #23539: Set Content-Length to 0 for PUT, POST, and PATCH if body is None.
Diffstat (limited to 'Lib/http/client.py')
-rw-r--r--Lib/http/client.py37
1 files changed, 24 insertions, 13 deletions
diff --git a/Lib/http/client.py b/Lib/http/client.py
index d2709ae..f5889ed 100644
--- a/Lib/http/client.py
+++ b/Lib/http/client.py
@@ -138,6 +138,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
@@ -1068,19 +1072,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)
@@ -1096,8 +1107,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):