[Python-checkins] python/dist/src/Lib httplib.py,1.42.10.5,1.42.10.6

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
Tue, 02 Jul 2002 10:19:50 -0700


Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv10911/Lib

Modified Files:
      Tag: release22-maint
	httplib.py 
Log Message:
Backport various bug fixes from trunk.

The 2.2 maintenace branch is now identical to the trunk through rev
1.53.


Index: httplib.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v
retrieving revision 1.42.10.5
retrieving revision 1.42.10.6
diff -C2 -d -r1.42.10.5 -r1.42.10.6
*** httplib.py	20 Apr 2002 07:45:24 -0000	1.42.10.5
--- httplib.py	2 Jul 2002 17:19:47 -0000	1.42.10.6
***************
*** 79,86 ****
  __all__ = ["HTTP", "HTTPResponse", "HTTPConnection", "HTTPSConnection",
             "HTTPException", "NotConnected", "UnknownProtocol",
!            "UnknownTransferEncoding", "IllegalKeywordArgument",
!            "UnimplementedFileMode", "IncompleteRead",
!            "ImproperConnectionState", "CannotSendRequest", "CannotSendHeader",
!            "ResponseNotReady", "BadStatusLine", "error"]
  
  HTTP_PORT = 80
--- 79,86 ----
  __all__ = ["HTTP", "HTTPResponse", "HTTPConnection", "HTTPSConnection",
             "HTTPException", "NotConnected", "UnknownProtocol",
!            "UnknownTransferEncoding", "UnimplementedFileMode",
!            "IncompleteRead", "InvalidURL", "ImproperConnectionState",
!            "CannotSendRequest", "CannotSendHeader", "ResponseNotReady",
!            "BadStatusLine", "error"]
  
  HTTP_PORT = 80
***************
*** 112,120 ****
          self.will_close = _UNKNOWN      # conn will close at end of response
  
!     def begin(self):
!         if self.msg is not None:
!             # we've already started reading the response
!             return
! 
          line = self.fp.readline()
          if self.debuglevel > 0:
--- 112,116 ----
          self.will_close = _UNKNOWN      # conn will close at end of response
  
!     def _read_status(self):
          line = self.fp.readline()
          if self.debuglevel > 0:
***************
*** 136,146 ****
          # The status code is a three-digit number
          try:
!             self.status = status = int(status)
              if status < 100 or status > 999:
                  raise BadStatusLine(line)
          except ValueError:
              raise BadStatusLine(line)
!         self.reason = reason.strip()
  
          if version == 'HTTP/1.0':
              self.version = 10
--- 132,162 ----
          # The status code is a three-digit number
          try:
!             status = int(status)
              if status < 100 or status > 999:
                  raise BadStatusLine(line)
          except ValueError:
              raise BadStatusLine(line)
!         return version, status, reason
! 
!     def _begin(self):
!         if self.msg is not None:
!             # we've already started reading the response
!             return
  
+         # read until we get a non-100 response
+         while 1:
+             version, status, reason = self._read_status()
+             if status != 100:
+                 break
+             # skip the header from the 100 response
+             while 1:
+                 skip = self.fp.readline().strip()
+                 if not skip:
+                     break
+                 if self.debuglevel > 0:
+                     print "header:", skip
+             
+         self.status = status
+         self.reason = reason.strip()
          if version == 'HTTP/1.0':
              self.version = 10
***************
*** 153,156 ****
--- 169,173 ----
  
          if self.version == 9:
+             self.chunked = 0
              self.msg = mimetools.Message(StringIO())
              return
***************
*** 234,237 ****
--- 251,255 ----
  
          if self.chunked:
+             assert self.chunked != _UNKNOWN
              chunk_left = self.chunk_left
              value = ''
***************
*** 348,352 ****
              i = host.find(':')
              if i >= 0:
!                 port = int(host[i+1:])
                  host = host[:i]
              else:
--- 366,373 ----
              i = host.find(':')
              if i >= 0:
!                 try:
!                     port = int(host[i+1:])
!                 except ValueError:
!                     raise InvalidURL, "nonnumeric port: '%s'"%host[i+1:]
                  host = host[:i]
              else:
***************
*** 361,365 ****
          """Connect to the host and port specified in __init__."""
          msg = "getaddrinfo returns an empty list"
!         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
              af, socktype, proto, canonname, sa = res
              try:
--- 382,387 ----
          """Connect to the host and port specified in __init__."""
          msg = "getaddrinfo returns an empty list"
!         for res in socket.getaddrinfo(self.host, self.port, 0,
!                                       socket.SOCK_STREAM):
              af, socktype, proto, canonname, sa = res
              try:
***************
*** 547,551 ****
          # optional skip_host argument to putrequest().  The check is
          # harder because field names are case insensitive.
!         if (headers.has_key('Host')
              or [k for k in headers.iterkeys() if k.lower() == "host"]):
              self.putrequest(method, url, skip_host=1)
--- 569,573 ----
          # optional skip_host argument to putrequest().  The check is
          # harder because field names are case insensitive.
!         if 'Host' in (headers
              or [k for k in headers.iterkeys() if k.lower() == "host"]):
              self.putrequest(method, url, skip_host=1)
***************
*** 593,597 ****
              response = self.response_class(self.sock)
  
!         response.begin()
          self.__state = _CS_IDLE
  
--- 615,620 ----
              response = self.response_class(self.sock)
  
!         response._begin()
!         assert response.will_close != _UNKNOWN
          self.__state = _CS_IDLE
  
***************
*** 605,637 ****
          return response
  
  
! class FakeSocket:
!     def __init__(self, sock, ssl):
!         self.__sock = sock
!         self.__ssl = ssl
! 
!     def makefile(self, mode, bufsize=None):
!         """Return a readable file-like object with data from socket.
! 
!         This method offers only partial support for the makefile
!         interface of a real socket.  It only supports modes 'r' and
!         'rb' and the bufsize argument is ignored.
! 
!         The returned object contains *all* of the file data
!         """
!         if mode != 'r' and mode != 'rb':
!             raise UnimplementedFileMode()
  
!         msgbuf = []
          while 1:
              try:
!                 buf = self.__ssl.read()
              except socket.sslerror, err:
                  if (err[0] == socket.SSL_ERROR_WANT_READ
!                     or err[0] == socket.SSL_ERROR_WANT_WRITE
!                     or 0):
                      continue
!                 if (err[0] == socket.SSL_ERROR_ZERO_RETURN 
! 			or err[0] == socket.SSL_ERROR_EOF):
                      break
                  raise
--- 628,654 ----
          return response
  
+ class SSLFile:
+     """File-like object wrapping an SSL socket."""
  
!     BUFSIZE = 8192
!     
!     def __init__(self, sock, ssl, bufsize=None):
!         self._sock = sock
!         self._ssl = ssl
!         self._buf = ''
!         self._bufsize = bufsize or self.__class__.BUFSIZE
  
!     def _read(self):
!         buf = ''
!         # put in a loop so that we retry on transient errors
          while 1:
              try:
!                 buf = self._ssl.read(self._bufsize)
              except socket.sslerror, err:
                  if (err[0] == socket.SSL_ERROR_WANT_READ
!                     or err[0] == socket.SSL_ERROR_WANT_WRITE):
                      continue
!                 if (err[0] == socket.SSL_ERROR_ZERO_RETURN
!                     or err[0] == socket.SSL_ERROR_EOF):
                      break
                  raise
***************
*** 639,647 ****
                  if err[0] == errno.EINTR:
                      continue
                  raise
!             if buf == '':
                  break
!             msgbuf.append(buf)
!         return StringIO("".join(msgbuf))
  
      def send(self, stuff, flags = 0):
--- 656,718 ----
                  if err[0] == errno.EINTR:
                      continue
+                 if err[0] == errno.EBADF:
+                     # XXX socket was closed?
+                     break
                  raise
!             else:
                  break
!         return buf
! 
!     def read(self, size=None):
!         L = [self._buf]
!         avail = len(self._buf)
!         while size is None or avail < size:
!             s = self._read()
!             if s == '':
!                 break
!             L.append(s)
!             avail += len(s)
!         all = "".join(L)
!         if size is None:
!             self._buf = ''
!             return all
!         else:
!             self._buf = all[size:]
!             return all[:size]
! 
!     def readline(self):
!         L = [self._buf]
!         self._buf = ''
!         while 1:
!             i = L[-1].find("\n")
!             if i >= 0:
!                 break
!             s = self._read()
!             if s == '':
!                 break
!             L.append(s)
!         if i == -1:
!             # loop exited because there is no more data
!             return "".join(L)
!         else:
!             all = "".join(L)
!             # XXX could do enough bookkeeping not to do a 2nd search
!             i = all.find("\n") + 1
!             line = all[:i]
!             self._buf = all[i:]
!             return line
! 
!     def close(self):
!         self._sock.close()
! 
! class FakeSocket:
!     def __init__(self, sock, ssl):
!         self.__sock = sock
!         self.__ssl = ssl
! 
!     def makefile(self, mode, bufsize=None):
!         if mode != 'r' and mode != 'rb':
!             raise UnimplementedFileMode()
!         return SSLFile(self.__sock, self.__ssl, bufsize)
  
      def send(self, stuff, flags = 0):
***************
*** 663,681 ****
      default_port = HTTPS_PORT
  
!     def __init__(self, host, port=None, **x509):
!         keys = x509.keys()
!         try:
!             keys.remove('key_file')
!         except ValueError:
!             pass
!         try:
!             keys.remove('cert_file')
!         except ValueError:
!             pass
!         if keys:
!             raise IllegalKeywordArgument()
          HTTPConnection.__init__(self, host, port)
!         self.key_file = x509.get('key_file')
!         self.cert_file = x509.get('cert_file')
  
      def connect(self):
--- 734,741 ----
      default_port = HTTPS_PORT
  
!     def __init__(self, host, port=None, key_file=None, cert_file=None):
          HTTPConnection.__init__(self, host, port)
!         self.key_file = key_file
!         self.cert_file = cert_file
  
      def connect(self):
***************
*** 811,814 ****
--- 871,877 ----
      pass
  
+ class InvalidURL(HTTPException):
+     pass
+ 
  class UnknownProtocol(HTTPException):
      def __init__(self, version):
***************
*** 818,824 ****
      pass
  
- class IllegalKeywordArgument(HTTPException):
-     pass
- 
  class UnimplementedFileMode(HTTPException):
      pass
--- 881,884 ----
***************
*** 881,885 ****
          for header in headers.headers: print header.strip()
      print
!     print h.getfile().read()
  
      # minimal test that code to extract host from url works
--- 941,945 ----
          for header in headers.headers: print header.strip()
      print
!     print "read", len(h.getfile().read())
  
      # minimal test that code to extract host from url works
***************
*** 902,905 ****
--- 962,966 ----
          hs.endheaders()
          status, reason, headers = hs.getreply()
+         # XXX why does this give a 302 response?
          print 'status =', status
          print 'reason =', reason
***************
*** 908,912 ****
              for header in headers.headers: print header.strip()
          print
!         print hs.getfile().read()
  
  
--- 969,973 ----
              for header in headers.headers: print header.strip()
          print
!         print "read", len(hs.getfile().read())