diff options
Diffstat (limited to 'Lib/http/client.py')
-rw-r--r-- | Lib/http/client.py | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/Lib/http/client.py b/Lib/http/client.py index a4ec8e5..99d560e 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -693,7 +693,7 @@ class HTTPConnection: """ self._buffer.append(s) - def _send_output(self): + def _send_output(self, message_body=None): """Send the currently buffered request and clear the buffer. Appends an extra \\r\\n to the buffer. @@ -701,6 +701,11 @@ class HTTPConnection: self._buffer.extend((b"", b"")) msg = b"\r\n".join(self._buffer) del self._buffer[:] + # If msg and message_body are sent in a single send() call, + # it will avoid performance problems caused by the interaction + # between delayed ack and the Nagle algorithim. + if message_body is not None: + msg += message_body self.send(msg) def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): @@ -830,15 +835,20 @@ class HTTPConnection: header = header + b': ' + value self._output(header) - def endheaders(self): - """Indicate that the last header line has been sent to the server.""" + def endheaders(self, message_body=None): + """Indicate that the last header line has been sent to the server. + This method sends the request to the server. The optional + message_body argument can be used to pass message body + associated with the request. The message body will be sent in + the same packet as the message headers if possible. The + message_body should be a string. + """ if self.__state == _CS_REQ_STARTED: self.__state = _CS_REQ_SENT else: raise CannotSendHeader() - - self._send_output() + self._send_output(message_body) def request(self, method, url, body=None, headers={}): """Send a complete request to the server.""" @@ -851,6 +861,24 @@ class HTTPConnection: # try one more time self._send_request(method, url, body, headers) + def _set_content_length(self, body): + # Set the content-length based on the body. + thelen = None + try: + thelen = str(len(body)) + except TypeError as te: + # If this is a file-like object, try to + # fstat its file descriptor + import os + 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) + def _send_request(self, method, url, body, headers): # honour explicitly requested Host: and Accept-Encoding headers header_names = dict.fromkeys([k.lower() for k in headers]) @@ -863,28 +891,15 @@ class HTTPConnection: self.putrequest(method, url, **skips) if body and ('content-length' not in header_names): - thelen = None - try: - thelen = str(len(body)) - except TypeError as te: - # If this is a file-like object, try to - # fstat its file descriptor - import os - 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) + self._set_content_length(body) for hdr, value in headers.items(): self.putheader(hdr, value) - self.endheaders() - - if body: - if isinstance(body, str): body = body.encode('ascii') - self.send(body) + if isinstance(body, str): + self.endheaders(body.encode('ascii')) + else: + self.endheaders() + if body: # when body is a file rather than a string + self.send(body) def getresponse(self): """Get the response from the server.""" |