Mailing List Archive

python/dist/src/Lib httplib.py,1.42.10.5,1.42.10.6
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())