Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1742e40

Browse files
committed
Merged revisions 67442 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r67442 | jeremy.hylton | 2008-11-28 19:09:35 -0600 (Fri, 28 Nov 2008) | 18 lines Send HTTP headers and message body in a single send() call. This change addresses part of issue 4336. Change endheaders() to take an optional message_body argument that is sent along with the headers. Change xmlrpclib and httplib's other methods to use this new interface. It is more efficient to make a single send() call, which should get the entire client request into one packet (assuming it is smaller than the MTU) and will avoid the long pause for delayed ack following timeout. Also: - Add a comment about the buffer size for makefile(). - Extract _set_content_length() method and fix whitespace issues there. ........
1 parent 45a6b9f commit 1742e40

1 file changed

Lines changed: 40 additions & 25 deletions

File tree

Lib/http/client.py

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -693,14 +693,19 @@ def _output(self, s):
693693
"""
694694
self._buffer.append(s)
695695

696-
def _send_output(self):
696+
def _send_output(self, message_body=None):
697697
"""Send the currently buffered request and clear the buffer.
698698
699699
Appends an extra \\r\\n to the buffer.
700700
"""
701701
self._buffer.extend((b"", b""))
702702
msg = b"\r\n".join(self._buffer)
703703
del self._buffer[:]
704+
# If msg and message_body are sent in a single send() call,
705+
# it will avoid performance problems caused by the interaction
706+
# between delayed ack and the Nagle algorithim.
707+
if message_body is not None:
708+
msg += message_body
704709
self.send(msg)
705710

706711
def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
@@ -830,15 +835,20 @@ def putheader(self, header, *values):
830835
header = header + b': ' + value
831836
self._output(header)
832837

833-
def endheaders(self):
834-
"""Indicate that the last header line has been sent to the server."""
838+
def endheaders(self, message_body=None):
839+
"""Indicate that the last header line has been sent to the server.
835840
841+
This method sends the request to the server. The optional
842+
message_body argument can be used to pass message body
843+
associated with the request. The message body will be sent in
844+
the same packet as the message headers if possible. The
845+
message_body should be a string.
846+
"""
836847
if self.__state == _CS_REQ_STARTED:
837848
self.__state = _CS_REQ_SENT
838849
else:
839850
raise CannotSendHeader()
840-
841-
self._send_output()
851+
self._send_output(message_body)
842852

843853
def request(self, method, url, body=None, headers={}):
844854
"""Send a complete request to the server."""
@@ -851,6 +861,24 @@ def request(self, method, url, body=None, headers={}):
851861
# try one more time
852862
self._send_request(method, url, body, headers)
853863

864+
def _set_content_length(self, body):
865+
# Set the content-length based on the body.
866+
thelen = None
867+
try:
868+
thelen = str(len(body))
869+
except TypeError as te:
870+
# If this is a file-like object, try to
871+
# fstat its file descriptor
872+
import os
873+
try:
874+
thelen = str(os.fstat(body.fileno()).st_size)
875+
except (AttributeError, OSError):
876+
# Don't send a length if this failed
877+
if self.debuglevel > 0: print("Cannot stat!!")
878+
879+
if thelen is not None:
880+
self.putheader('Content-Length', thelen)
881+
854882
def _send_request(self, method, url, body, headers):
855883
# honour explicitly requested Host: and Accept-Encoding headers
856884
header_names = dict.fromkeys([k.lower() for k in headers])
@@ -863,28 +891,15 @@ def _send_request(self, method, url, body, headers):
863891
self.putrequest(method, url, **skips)
864892

865893
if body and ('content-length' not in header_names):
866-
thelen = None
867-
try:
868-
thelen = str(len(body))
869-
except TypeError as te:
870-
# If this is a file-like object, try to
871-
# fstat its file descriptor
872-
import os
873-
try:
874-
thelen = str(os.fstat(body.fileno()).st_size)
875-
except (AttributeError, OSError):
876-
# Don't send a length if this failed
877-
if self.debuglevel > 0: print("Cannot stat!!")
878-
879-
if thelen is not None:
880-
self.putheader('Content-Length',thelen)
894+
self._set_content_length(body)
881895
for hdr, value in headers.items():
882896
self.putheader(hdr, value)
883-
self.endheaders()
884-
885-
if body:
886-
if isinstance(body, str): body = body.encode('ascii')
887-
self.send(body)
897+
if isinstance(body, str):
898+
self.endheaders(body.encode('ascii'))
899+
else:
900+
self.endheaders()
901+
if body: # when body is a file rather than a string
902+
self.send(body)
888903

889904
def getresponse(self):
890905
"""Get the response from the server."""

0 commit comments

Comments
 (0)