[Python-3000-checkins] r67460 - in python/branches/py3k: Lib/http/client.py

Jeremy Hylton jeremy at alum.mit.edu
Mon Dec 1 15:21:04 CET 2008


Thanks!  I was going to look at porting this change over the long
weekend, but the weekend part got the better of me :-).

Jeremy

On Sun, Nov 30, 2008 at 5:15 PM, benjamin.peterson
<python-3000-checkins at python.org> wrote:
> Author: benjamin.peterson
> Date: Sun Nov 30 23:15:29 2008
> New Revision: 67460
>
> Log:
> Merged revisions 67442 via svnmerge from
> svn+ssh://pythondev@svn.python.org/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.
> ........
>
>
> Modified:
>   python/branches/py3k/   (props changed)
>   python/branches/py3k/Lib/http/client.py
>
> Modified: python/branches/py3k/Lib/http/client.py
> ==============================================================================
> --- python/branches/py3k/Lib/http/client.py     (original)
> +++ python/branches/py3k/Lib/http/client.py     Sun Nov 30 23:15:29 2008
> @@ -693,7 +693,7 @@
>         """
>         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 @@
>         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 @@
>         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 @@
>             # 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 @@
>         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."""
> _______________________________________________
> Python-3000-checkins mailing list
> Python-3000-checkins at python.org
> http://mail.python.org/mailman/listinfo/python-3000-checkins
>


More information about the Python-3000-checkins mailing list