add support for HTTPS

Modify HTTP to use delegation instead of inheritance.  The
_connection_class attribute of the class defines what class to
delegate to.  The HTTPS class is a subclass of HTTP that redefines
_connection_class.
This commit is contained in:
Jeremy Hylton 2000-08-01 17:33:32 +00:00
parent 1c2b178ceb
commit 29b8d5acd0
1 changed files with 27 additions and 16 deletions

View File

@ -1,8 +1,3 @@
#
# HTTP/1.1 client library
#
# ### this may as well go into a doc string...
"""HTTP/1.1 client library """HTTP/1.1 client library
<intro stuff goes here> <intro stuff goes here>
@ -71,7 +66,6 @@ Req-started-unread-response _CS_REQ_STARTED <response_class>
Req-sent-unread-response _CS_REQ_SENT <response_class> Req-sent-unread-response _CS_REQ_SENT <response_class>
""" """
import socket import socket
import string import string
import mimetools import mimetools
@ -599,7 +593,7 @@ class HTTPSConnection(HTTPConnection):
self.sock = FakeSocket(sock, ssl) self.sock = FakeSocket(sock, ssl)
class HTTP(HTTPConnection): class HTTP:
"Compatibility class with httplib.py from 1.5." "Compatibility class with httplib.py from 1.5."
_http_vsn = 10 _http_vsn = 10
@ -607,6 +601,8 @@ class HTTP(HTTPConnection):
debuglevel = 0 debuglevel = 0
_connection_class = HTTPConnection
def __init__(self, host='', port=None, **x509): def __init__(self, host='', port=None, **x509):
"Provide a default host, since the superclass requires one." "Provide a default host, since the superclass requires one."
@ -617,7 +613,11 @@ class HTTP(HTTPConnection):
# Note that we may pass an empty string as the host; this will throw # Note that we may pass an empty string as the host; this will throw
# an error when we attempt to connect. Presumably, the client code # an error when we attempt to connect. Presumably, the client code
# will call connect before then, with a proper host. # will call connect before then, with a proper host.
HTTPConnection.__init__(self, host, port) self._conn = self._connection_class(host, port)
# set up delegation to flesh out interface
self.send = self._conn.send
self.putrequest = self._conn.putrequest
self.endheaders = self._conn.endheaders
# we never actually use these for anything, but we keep them here for # we never actually use these for anything, but we keep them here for
# compatibility with post-1.5.2 CVS. # compatibility with post-1.5.2 CVS.
@ -630,8 +630,8 @@ class HTTP(HTTPConnection):
"Accept arguments to set the host/port, since the superclass doesn't." "Accept arguments to set the host/port, since the superclass doesn't."
if host is not None: if host is not None:
self._set_hostport(host, port) self._conn._set_hostport(host, port)
HTTPConnection.connect(self) self._conn.connect()
def set_debuglevel(self, debuglevel): def set_debuglevel(self, debuglevel):
"The class no longer supports the debuglevel." "The class no longer supports the debuglevel."
@ -643,8 +643,8 @@ class HTTP(HTTPConnection):
def putheader(self, header, *values): def putheader(self, header, *values):
"The superclass allows only one value argument." "The superclass allows only one value argument."
HTTPConnection.putheader(self, header, self._conn.putheader(header,
string.joinfields(values, '\r\n\t')) string.joinfields(values, '\r\n\t'))
def getreply(self): def getreply(self):
"""Compat definition since superclass does not define it. """Compat definition since superclass does not define it.
@ -655,14 +655,14 @@ class HTTP(HTTPConnection):
- any RFC822 headers in the response from the server - any RFC822 headers in the response from the server
""" """
try: try:
response = self.getresponse() response = self._conn.getresponse()
except BadStatusLine, e: except BadStatusLine, e:
### hmm. if getresponse() ever closes the socket on a bad request, ### hmm. if getresponse() ever closes the socket on a bad request,
### then we are going to have problems with self.sock ### then we are going to have problems with self.sock
### should we keep this behavior? do people use it? ### should we keep this behavior? do people use it?
# keep the socket open (as a file), and return it # keep the socket open (as a file), and return it
self.file = self.sock.makefile('rb', 0) self.file = self._conn.sock.makefile('rb', 0)
# close our socket -- we want to restart after any protocol error # close our socket -- we want to restart after any protocol error
self.close() self.close()
@ -675,7 +675,7 @@ class HTTP(HTTPConnection):
return response.status, response.reason, response.msg return response.status, response.reason, response.msg
def close(self): def close(self):
HTTPConnection.close(self) self._conn.close()
# note that self.file == response.fp, which gets closed by the # note that self.file == response.fp, which gets closed by the
# superclass. just clear the object ref here. # superclass. just clear the object ref here.
@ -684,6 +684,17 @@ class HTTP(HTTPConnection):
### do it ### do it
self.file = None self.file = None
if hasattr(socket, 'ssl'):
class HTTPS(HTTP):
"""Compatibility with 1.5 httplib interface
Python 1.5.2 did not have an HTTPS class, but it defined an
interface for sending http requests that is also useful for
https.
"""
_connection_class = HTTPSConnection
class HTTPException(Exception): class HTTPException(Exception):
pass pass
@ -764,7 +775,7 @@ def test():
print h.getfile().read() print h.getfile().read()
if hasattr(socket, 'ssl'): if hasattr(socket, 'ssl'):
host = 'www.c2.net' host = 'sourceforge.net'
hs = HTTPS() hs = HTTPS()
hs.connect(host) hs.connect(host)
hs.putrequest('GET', selector) hs.putrequest('GET', selector)