Index: Lib/httplib.py =================================================================== --- Lib/httplib.py (revision 67120) +++ Lib/httplib.py (working copy) @@ -325,8 +325,8 @@ # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details. - def __init__(self, sock, debuglevel=0, strict=0, method=None): - self.fp = sock.makefile('rb', 0) + def __init__(self, sock, debuglevel=0, strict=0, method=None, bufsize=0): + self.fp = sock.makefile('rb', bufsize) self.debuglevel = debuglevel self.strict = strict self._method = method @@ -729,7 +729,7 @@ """ self._buffer.append(s) - def _send_output(self): + def _get_output(self): """Send the currently buffered request and clear the buffer. Appends an extra \\r\\n to the buffer. @@ -737,8 +737,8 @@ self._buffer.extend(("", "")) msg = "\r\n".join(self._buffer) del self._buffer[:] - self.send(msg) - + return msg + def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): """Send a request to the server. @@ -859,13 +859,19 @@ def endheaders(self): """Indicate that the last header line has been sent to the server.""" - + self.send(self.getheaderdata()) + + def getheaderdata(self): + """Same as endheader(), only returns the header data. This is useful + if a send() will follow, so that it can be prepended to it. This helps + avoid the Nagle/delayed ACK TCP performance problem. + """ if self.__state == _CS_REQ_STARTED: self.__state = _CS_REQ_SENT else: raise CannotSendHeader() - self._send_output() + return self._get_output() def request(self, method, url, body=None, headers={}): """Send a complete request to the server.""" @@ -908,12 +914,13 @@ self.putheader('Content-Length',thelen) for hdr, value in headers.iteritems(): self.putheader(hdr, value) - self.endheaders() if body: - self.send(body) + self.send(self.getheaderdata()+body) + else: + self.endheaders() - def getresponse(self): + def getresponse(self, bufsize=0): "Get the response from the server." # if a prior response has been completed, then forget about it. @@ -942,10 +949,12 @@ if self.debuglevel > 0: response = self.response_class(self.sock, self.debuglevel, strict=self.strict, - method=self._method) + method=self._method, + bufsize=bufsize) else: response = self.response_class(self.sock, strict=self.strict, - method=self._method) + method=self._method, + bufsize=bufsize) response.begin() assert response.will_close != _UNKNOWN @@ -989,6 +998,7 @@ # set up delegation to flesh out interface self.send = conn.send self.putrequest = conn.putrequest + self.getheaderdata = conn.getheaderdata self.endheaders = conn.endheaders self.set_debuglevel = conn.set_debuglevel @@ -1012,7 +1022,7 @@ "The superclass allows only one value argument." self._conn.putheader(header, '\r\n\t'.join(values)) - def getreply(self): + def getreply(self, bufsize=0): """Compat definition since superclass does not define it. Returns a tuple consisting of: @@ -1021,14 +1031,14 @@ - any RFC822 headers in the response from the server """ try: - response = self._conn.getresponse() + response = self._conn.getresponse(bufsize) except BadStatusLine, e: ### hmm. if getresponse() ever closes the socket on a bad request, ### then we are going to have problems with self.sock ### should we keep this behavior? do people use it? # keep the socket open (as a file), and return it - self.file = self._conn.sock.makefile('rb', 0) + self.file = self._conn.sock.makefile('rb', bufsize) # close our socket -- we want to restart after any protocol error self.close() Index: Lib/xmlrpclib.py =================================================================== --- Lib/xmlrpclib.py (revision 67120) +++ Lib/xmlrpclib.py (working copy) @@ -1234,7 +1234,9 @@ self.send_user_agent(h) self.send_content(h, request_body) - errcode, errmsg, headers = h.getreply() + #we will perform readline() on the h.getfile() so we need + #default buffering + errcode, errmsg, headers = h.getreply(bufsize = -1) if errcode != 200: raise ProtocolError( @@ -1346,9 +1348,10 @@ def send_content(self, connection, request_body): connection.putheader("Content-Type", "text/xml") connection.putheader("Content-Length", str(len(request_body))) - connection.endheaders() if request_body: - connection.send(request_body) + connection.send(connection.getheaderdata()+request_body) + else: + connection.endheaders() ## # Parse response.