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 @@ -734,10 +734,17 @@ Appends an extra \\r\\n to the buffer. """ + self.send(self._get_output()) + + def _get_output(self): + """Get the currently buffered request and clear the buffer. + + Appends an extra \\r\\n to the buffer. + """ 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. @@ -857,15 +864,23 @@ str = '%s: %s' % (header, value) self._output(str) - def endheaders(self): - """Indicate that the last header line has been sent to the server.""" - + def endheaders(self, send_data=True): + """Indicate that the last header line has been sent to the server. + The optional send_data can be set to False, and so specifies that + the data is not to be sent over the wire, only returned. + This is useful if a send() will follow, so that both can be sent + At the same time. This helps avoid the dreaded Nagle/delayed ACK TCP + performance problem. + The function returns any unsent data, regardless of return_data. + """ if self.__state == _CS_REQ_STARTED: self.__state = _CS_REQ_SENT else: raise CannotSendHeader() - + if not send_data: + return self._get_output() self._send_output() + return "" def request(self, method, url, body=None, headers={}): """Send a complete request to the server.""" @@ -908,12 +923,15 @@ self.putheader('Content-Length',thelen) for hdr, value in headers.iteritems(): self.putheader(hdr, value) - self.endheaders() + if isinstance(body, str): + header_data = self.endheaders(False) - if body: + self.send(header_data + body) + else: + self.sendheaders(True) self.send(body) - 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 +960,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 @@ -1012,7 +1032,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 +1041,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/test/test_xmlrpc.py =================================================================== --- Lib/test/test_xmlrpc.py (revision 67120) +++ Lib/test/test_xmlrpc.py (working copy) @@ -647,7 +647,9 @@ # 10035 (WSAEWOULDBLOCK) in the server thread handle_request call when # run on Windows. This only happens on the first test to run, but it # fails every time and so these tests are skipped on win32 platforms. - if sys.platform != 'win32': + # Update, nov 2008: This appears no longer to be the case, so they + # are included regardless + if True or sys.platform != 'win32': xmlrpc_tests.append(SimpleServerTestCase) xmlrpc_tests.append(FailingServerTestCase) xmlrpc_tests.append(CGIHandlerTestCase) 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,8 @@ 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) + header_data = connection.endheaders(False) + connection.send(header_data + request_body) ## # Parse response.