Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/httplib.py

    r2 r391  
    1 """HTTP/1.1 client library
     1r"""HTTP/1.1 client library
    22
    33<intro stuff goes here>
     
    6868
    6969from array import array
     70import os
    7071import socket
    7172from sys import py3kwarning
     
    212213MAXAMOUNT = 1048576
    213214
     215# maximal line length when calling readline().
     216_MAXLINE = 65536
     217
    214218class HTTPMessage(mimetools.Message):
    215219
     
    274278                    startofline = tell = None
    275279                    self.seekable = 0
    276             line = self.fp.readline()
     280            line = self.fp.readline(_MAXLINE + 1)
     281            if len(line) > _MAXLINE:
     282                raise LineTooLong("header line")
    277283            if not line:
    278284                self.status = 'EOF in headers'
     
    327333    # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.
    328334
    329     def __init__(self, sock, debuglevel=0, strict=0, method=None):
    330         self.fp = sock.makefile('rb', 0)
     335    def __init__(self, sock, debuglevel=0, strict=0, method=None, buffering=False):
     336        if buffering:
     337            # The caller won't be using any sock.recv() calls, so buffering
     338            # is fine and recommended for performance.
     339            self.fp = sock.makefile('rb')
     340        else:
     341            # The buffer size is specified as zero, because the headers of
     342            # the response are read with readline().  If the reads were
     343            # buffered the readline() calls could consume some of the
     344            # response, which make be read via a recv() on the underlying
     345            # socket.
     346            self.fp = sock.makefile('rb', 0)
    331347        self.debuglevel = debuglevel
    332348        self.strict = strict
     
    347363    def _read_status(self):
    348364        # Initialize with Simple-Response defaults
    349         line = self.fp.readline()
     365        line = self.fp.readline(_MAXLINE + 1)
     366        if len(line) > _MAXLINE:
     367            raise LineTooLong("header line")
    350368        if self.debuglevel > 0:
    351369            print "reply:", repr(line)
     
    394412            # skip the header from the 100 response
    395413            while True:
    396                 skip = self.fp.readline().strip()
     414                skip = self.fp.readline(_MAXLINE + 1)
     415                if len(skip) > _MAXLINE:
     416                    raise LineTooLong("header line")
     417                skip = skip.strip()
    397418                if not skip:
    398419                    break
     
    515536            return ''
    516537
     538        if self._method == 'HEAD':
     539            self.close()
     540            return ''
     541
    517542        if self.chunked:
    518543            return self._read_chunked(amt)
     
    523548                s = self.fp.read()
    524549            else:
    525                 s = self._safe_read(self.length)
     550                try:
     551                    s = self._safe_read(self.length)
     552                except IncompleteRead:
     553                    self.close()
     554                    raise
    526555                self.length = 0
    527556            self.close()        # we read everything
     
    537566        # (for example, reading in 1k chunks)
    538567        s = self.fp.read(amt)
     568        if not s:
     569            # Ideally, we would raise IncompleteRead if the content-length
     570            # wasn't satisfied, but it might break compatibility.
     571            self.close()
    539572        if self.length is not None:
    540573            self.length -= len(s)
    541574            if not self.length:
    542575                self.close()
     576
    543577        return s
    544578
     
    549583        while True:
    550584            if chunk_left is None:
    551                 line = self.fp.readline()
     585                line = self.fp.readline(_MAXLINE + 1)
     586                if len(line) > _MAXLINE:
     587                    raise LineTooLong("chunk size")
    552588                i = line.find(';')
    553589                if i >= 0:
     
    584620        ### note: we shouldn't have any trailers!
    585621        while True:
    586             line = self.fp.readline()
     622            line = self.fp.readline(_MAXLINE + 1)
     623            if len(line) > _MAXLINE:
     624                raise LineTooLong("trailer line")
    587625            if not line:
    588626                # a vanishingly small number of sites EOF without
     
    611649        IncompleteRead exception can be used to detect the problem.
    612650        """
     651        # NOTE(gps): As of svn r74426 socket._fileobject.read(x) will never
     652        # return less than x bytes unless EOF is encountered.  It now handles
     653        # signal interruptions (socket.error EINTR) internally.  This code
     654        # never caught that exception anyways.  It seems largely pointless.
     655        # self.fp.read(amt) will work fine.
    613656        s = []
    614657        while amt > 0:
     
    620663        return ''.join(s)
    621664
     665    def fileno(self):
     666        return self.fp.fileno()
     667
    622668    def getheader(self, name, default=None):
    623669        if self.msg is None:
     
    644690
    645691    def __init__(self, host, port=None, strict=None,
    646                  timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
     692                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None):
    647693        self.timeout = timeout
     694        self.source_address = source_address
    648695        self.sock = None
    649696        self._buffer = []
     
    659706            self.strict = strict
    660707
    661     def _set_tunnel(self, host, port=None, headers=None):
     708    def set_tunnel(self, host, port=None, headers=None):
    662709        """ Sets up the host and the port for the HTTP CONNECT Tunnelling.
    663710
     
    680727                    port = int(host[i+1:])
    681728                except ValueError:
    682                     raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
     729                    if host[i+1:] == "":  # http://foo.com:/ == http://foo.com/
     730                        port = self.default_port
     731                    else:
     732                        raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
    683733                host = host[:i]
    684734            else:
     
    704754        if code != 200:
    705755            self.close()
    706             raise socket.error, "Tunnel connection failed: %d %s" % (code,
    707                                                                      message.strip())
     756            raise socket.error("Tunnel connection failed: %d %s" % (code,
     757                                                                    message.strip()))
    708758        while True:
    709             line = response.fp.readline()
    710             if line == '\r\n': break
     759            line = response.fp.readline(_MAXLINE + 1)
     760            if len(line) > _MAXLINE:
     761                raise LineTooLong("header line")
     762            if not line:
     763                # for sites which EOF without sending trailer
     764                break
     765            if line == '\r\n':
     766                break
    711767
    712768
     
    714770        """Connect to the host and port specified in __init__."""
    715771        self.sock = socket.create_connection((self.host,self.port),
    716                                              self.timeout)
     772                                             self.timeout, self.source_address)
    717773
    718774        if self._tunnel_host:
     
    729785        self.__state = _CS_IDLE
    730786
    731     def send(self, str):
    732         """Send `str' to the server."""
     787    def send(self, data):
     788        """Send `data' to the server."""
    733789        if self.sock is None:
    734790            if self.auto_open:
     
    737793                raise NotConnected()
    738794
    739         # send the data to the server. if we get a broken pipe, then close
    740         # the socket. we want to reconnect when somebody tries to send again.
    741         #
    742         # NOTE: we DO propagate the error, though, because we cannot simply
    743         #       ignore the error... the caller will know if they can retry.
    744795        if self.debuglevel > 0:
    745             print "send:", repr(str)
    746         try:
    747             blocksize=8192
    748             if hasattr(str,'read') and not isinstance(str, array):
    749                 if self.debuglevel > 0: print "sendIng a read()able"
    750                 data=str.read(blocksize)
    751                 while data:
    752                     self.sock.sendall(data)
    753                     data=str.read(blocksize)
    754             else:
    755                 self.sock.sendall(str)
    756         except socket.error, v:
    757             if v[0] == 32:      # Broken pipe
    758                 self.close()
    759             raise
     796            print "send:", repr(data)
     797        blocksize = 8192
     798        if hasattr(data,'read') and not isinstance(data, array):
     799            if self.debuglevel > 0: print "sendIng a read()able"
     800            datablock = data.read(blocksize)
     801            while datablock:
     802                self.sock.sendall(datablock)
     803                datablock = data.read(blocksize)
     804        else:
     805            self.sock.sendall(data)
    760806
    761807    def _output(self, s):
     
    766812        self._buffer.append(s)
    767813
    768     def _send_output(self):
     814    def _send_output(self, message_body=None):
    769815        """Send the currently buffered request and clear the buffer.
    770816
    771817        Appends an extra \\r\\n to the buffer.
     818        A message_body may be specified, to be appended to the request.
    772819        """
    773820        self._buffer.extend(("", ""))
    774821        msg = "\r\n".join(self._buffer)
    775822        del self._buffer[:]
     823        # If msg and message_body are sent in a single send() call,
     824        # it will avoid performance problems caused by the interaction
     825        # between delayed ack and the Nagle algorithm.
     826        if isinstance(message_body, str):
     827            msg += message_body
     828            message_body = None
    776829        self.send(msg)
     830        if message_body is not None:
     831            #message_body was not a string (i.e. it is a file) and
     832            #we must run the risk of Nagle
     833            self.send(message_body)
    777834
    778835    def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
     
    818875        if not url:
    819876            url = '/'
    820         str = '%s %s %s' % (method, url, self._http_vsn_str)
    821 
    822         self._output(str)
     877        hdr = '%s %s %s' % (method, url, self._http_vsn_str)
     878
     879        self._output(hdr)
    823880
    824881        if self._http_vsn == 11:
     
    855912                    except UnicodeEncodeError:
    856913                        host_enc = self.host.encode("idna")
     914                    # Wrap the IPv6 Host Header with [] (RFC 2732)
     915                    if host_enc.find(':') >= 0:
     916                        host_enc = "[" + host_enc + "]"
    857917                    if self.port == self.default_port:
    858918                        self.putheader('Host', host_enc)
     
    883943            pass
    884944
    885     def putheader(self, header, value):
     945    def putheader(self, header, *values):
    886946        """Send a request header line to the server.
    887947
     
    891951            raise CannotSendHeader()
    892952
    893         str = '%s: %s' % (header, value)
    894         self._output(str)
    895 
    896     def endheaders(self):
    897         """Indicate that the last header line has been sent to the server."""
    898 
     953        hdr = '%s: %s' % (header, '\r\n\t'.join([str(v) for v in values]))
     954        self._output(hdr)
     955
     956    def endheaders(self, message_body=None):
     957        """Indicate that the last header line has been sent to the server.
     958
     959        This method sends the request to the server.  The optional
     960        message_body argument can be used to pass a message body
     961        associated with the request.  The message body will be sent in
     962        the same packet as the message headers if it is string, otherwise it is
     963        sent as a separate packet.
     964        """
    899965        if self.__state == _CS_REQ_STARTED:
    900966            self.__state = _CS_REQ_SENT
    901967        else:
    902968            raise CannotSendHeader()
    903 
    904         self._send_output()
     969        self._send_output(message_body)
    905970
    906971    def request(self, method, url, body=None, headers={}):
    907972        """Send a complete request to the server."""
    908 
     973        self._send_request(method, url, body, headers)
     974
     975    def _set_content_length(self, body):
     976        # Set the content-length based on the body.
     977        thelen = None
    909978        try:
    910             self._send_request(method, url, body, headers)
    911         except socket.error, v:
    912             # trap 'Broken pipe' if we're allowed to automatically reconnect
    913             if v[0] != 32 or not self.auto_open:
    914                 raise
    915             # try one more time
    916             self._send_request(method, url, body, headers)
     979            thelen = str(len(body))
     980        except TypeError, te:
     981            # If this is a file-like object, try to
     982            # fstat its file descriptor
     983            try:
     984                thelen = str(os.fstat(body.fileno()).st_size)
     985            except (AttributeError, OSError):
     986                # Don't send a length if this failed
     987                if self.debuglevel > 0: print "Cannot stat!!"
     988
     989        if thelen is not None:
     990            self.putheader('Content-Length', thelen)
    917991
    918992    def _send_request(self, method, url, body, headers):
    919         # honour explicitly requested Host: and Accept-Encoding headers
     993        # Honor explicitly requested Host: and Accept-Encoding: headers.
    920994        header_names = dict.fromkeys([k.lower() for k in headers])
    921995        skips = {}
     
    9271001        self.putrequest(method, url, **skips)
    9281002
    929         if body and ('content-length' not in header_names):
    930             thelen=None
    931             try:
    932                 thelen=str(len(body))
    933             except TypeError, te:
    934                 # If this is a file-like object, try to
    935                 # fstat its file descriptor
    936                 import os
    937                 try:
    938                     thelen = str(os.fstat(body.fileno()).st_size)
    939                 except (AttributeError, OSError):
    940                     # Don't send a length if this failed
    941                     if self.debuglevel > 0: print "Cannot stat!!"
    942 
    943             if thelen is not None:
    944                 self.putheader('Content-Length',thelen)
     1003        if body is not None and 'content-length' not in header_names:
     1004            self._set_content_length(body)
    9451005        for hdr, value in headers.iteritems():
    9461006            self.putheader(hdr, value)
    947         self.endheaders()
    948 
    949         if body:
    950             self.send(body)
    951 
    952     def getresponse(self):
     1007        self.endheaders(body)
     1008
     1009    def getresponse(self, buffering=False):
    9531010        "Get the response from the server."
    9541011
     
    9761033            raise ResponseNotReady()
    9771034
     1035        args = (self.sock,)
     1036        kwds = {"strict":self.strict, "method":self._method}
    9781037        if self.debuglevel > 0:
    979             response = self.response_class(self.sock, self.debuglevel,
    980                                            strict=self.strict,
    981                                            method=self._method)
    982         else:
    983             response = self.response_class(self.sock, strict=self.strict,
    984                                            method=self._method)
     1038            args += (self.debuglevel,)
     1039        if buffering:
     1040            #only add this keyword if non-default, for compatibility with
     1041            #other response_classes.
     1042            kwds["buffering"] = True;
     1043        response = self.response_class(*args, **kwds)
    9851044
    9861045        response.begin()
     
    10151074            port = None
    10161075
    1017         # Note that we may pass an empty string as the host; this will throw
     1076        # Note that we may pass an empty string as the host; this will raise
    10181077        # an error when we attempt to connect. Presumably, the client code
    10191078        # will call connect before then, with a proper host.
     
    10261085        self.send = conn.send
    10271086        self.putrequest = conn.putrequest
     1087        self.putheader = conn.putheader
    10281088        self.endheaders = conn.endheaders
    10291089        self.set_debuglevel = conn.set_debuglevel
     
    10451105        return self.file
    10461106
    1047     def putheader(self, header, *values):
    1048         "The superclass allows only one value argument."
    1049         self._conn.putheader(header, '\r\n\t'.join(values))
    1050 
    1051     def getreply(self):
     1107    def getreply(self, buffering=False):
    10521108        """Compat definition since superclass does not define it.
    10531109
     
    10581114        """
    10591115        try:
    1060             response = self._conn.getresponse()
     1116            if not buffering:
     1117                response = self._conn.getresponse()
     1118            else:
     1119                #only add this keyword if non-default for compatibility
     1120                #with other connection classes
     1121                response = self._conn.getresponse(buffering)
    10611122        except BadStatusLine, e:
    10621123            ### hmm. if getresponse() ever closes the socket on a bad request,
     
    10981159
    10991160        def __init__(self, host, port=None, key_file=None, cert_file=None,
    1100                      strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
    1101             HTTPConnection.__init__(self, host, port, strict, timeout)
     1161                     strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
     1162                     source_address=None):
     1163            HTTPConnection.__init__(self, host, port, strict, timeout,
     1164                                    source_address)
    11021165            self.key_file = key_file
    11031166            self.cert_file = cert_file
     
    11061169            "Connect to a host on a given (SSL) port."
    11071170
    1108             sock = socket.create_connection((self.host, self.port), self.timeout)
     1171            sock = socket.create_connection((self.host, self.port),
     1172                                            self.timeout, self.source_address)
    11091173            if self._tunnel_host:
    11101174                self.sock = sock
     
    11971261class BadStatusLine(HTTPException):
    11981262    def __init__(self, line):
     1263        if not line:
     1264            line = repr(line)
    11991265        self.args = line,
    12001266        self.line = line
     1267
     1268class LineTooLong(HTTPException):
     1269    def __init__(self, line_type):
     1270        HTTPException.__init__(self, "got more than %d bytes when reading %s"
     1271                                     % (_MAXLINE, line_type))
    12011272
    12021273# for backwards compatibility
     
    12701341        else:
    12711342            return L + self._file.readlines(size)
    1272 
    1273 def test():
    1274     """Test this module.
    1275 
    1276     A hodge podge of tests collected here, because they have too many
    1277     external dependencies for the regular test suite.
    1278     """
    1279 
    1280     import sys
    1281     import getopt
    1282     opts, args = getopt.getopt(sys.argv[1:], 'd')
    1283     dl = 0
    1284     for o, a in opts:
    1285         if o == '-d': dl = dl + 1
    1286     host = 'www.python.org'
    1287     selector = '/'
    1288     if args[0:]: host = args[0]
    1289     if args[1:]: selector = args[1]
    1290     h = HTTP()
    1291     h.set_debuglevel(dl)
    1292     h.connect(host)
    1293     h.putrequest('GET', selector)
    1294     h.endheaders()
    1295     status, reason, headers = h.getreply()
    1296     print 'status =', status
    1297     print 'reason =', reason
    1298     print "read", len(h.getfile().read())
    1299     print
    1300     if headers:
    1301         for header in headers.headers: print header.strip()
    1302     print
    1303 
    1304     # minimal test that code to extract host from url works
    1305     class HTTP11(HTTP):
    1306         _http_vsn = 11
    1307         _http_vsn_str = 'HTTP/1.1'
    1308 
    1309     h = HTTP11('www.python.org')
    1310     h.putrequest('GET', 'http://www.python.org/~jeremy/')
    1311     h.endheaders()
    1312     h.getreply()
    1313     h.close()
    1314 
    1315     try:
    1316         import ssl
    1317     except ImportError:
    1318         pass
    1319     else:
    1320 
    1321         for host, selector in (('sourceforge.net', '/projects/python'),
    1322                                ):
    1323             print "https://%s%s" % (host, selector)
    1324             hs = HTTPS()
    1325             hs.set_debuglevel(dl)
    1326             hs.connect(host)
    1327             hs.putrequest('GET', selector)
    1328             hs.endheaders()
    1329             status, reason, headers = hs.getreply()
    1330             print 'status =', status
    1331             print 'reason =', reason
    1332             print "read", len(hs.getfile().read())
    1333             print
    1334             if headers:
    1335                 for header in headers.headers: print header.strip()
    1336             print
    1337 
    1338 if __name__ == '__main__':
    1339     test()
Note: See TracChangeset for help on using the changeset viewer.