mirror of
https://github.com/python/cpython.git
synced 2025-11-24 20:30:18 +00:00
Remove Python 1.5 compatibility layer from httplib.
The two clients in the std library have been updated to use the newer interface. A couple of minor changes to the httplib tests were needed. Also, reformat some long lines in the httplib tests.
This commit is contained in:
parent
5d8a88a442
commit
3a38c91342
2 changed files with 15 additions and 191 deletions
178
Lib/httplib.py
178
Lib/httplib.py
|
|
@ -72,7 +72,7 @@ import mimetools
|
||||||
import socket
|
import socket
|
||||||
from urlparse import urlsplit
|
from urlparse import urlsplit
|
||||||
|
|
||||||
__all__ = ["HTTP", "HTTPResponse", "HTTPConnection", "HTTPSConnection",
|
__all__ = ["HTTPResponse", "HTTPConnection", "HTTPSConnection",
|
||||||
"HTTPException", "NotConnected", "UnknownProtocol",
|
"HTTPException", "NotConnected", "UnknownProtocol",
|
||||||
"UnknownTransferEncoding", "UnimplementedFileMode",
|
"UnknownTransferEncoding", "UnimplementedFileMode",
|
||||||
"IncompleteRead", "InvalidURL", "ImproperConnectionState",
|
"IncompleteRead", "InvalidURL", "ImproperConnectionState",
|
||||||
|
|
@ -1166,118 +1166,6 @@ class HTTPSConnection(HTTPConnection):
|
||||||
self.sock = FakeSocket(sock, ssl)
|
self.sock = FakeSocket(sock, ssl)
|
||||||
|
|
||||||
|
|
||||||
class HTTP:
|
|
||||||
"Compatibility class with httplib.py from 1.5."
|
|
||||||
|
|
||||||
_http_vsn = 10
|
|
||||||
_http_vsn_str = 'HTTP/1.0'
|
|
||||||
|
|
||||||
debuglevel = 0
|
|
||||||
|
|
||||||
_connection_class = HTTPConnection
|
|
||||||
|
|
||||||
def __init__(self, host='', port=None, strict=None):
|
|
||||||
"Provide a default host, since the superclass requires one."
|
|
||||||
|
|
||||||
# some joker passed 0 explicitly, meaning default port
|
|
||||||
if port == 0:
|
|
||||||
port = None
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# will call connect before then, with a proper host.
|
|
||||||
self._setup(self._connection_class(host, port, strict))
|
|
||||||
|
|
||||||
def _setup(self, conn):
|
|
||||||
self._conn = conn
|
|
||||||
|
|
||||||
# set up delegation to flesh out interface
|
|
||||||
self.send = conn.send
|
|
||||||
self.putrequest = conn.putrequest
|
|
||||||
self.endheaders = conn.endheaders
|
|
||||||
self.set_debuglevel = conn.set_debuglevel
|
|
||||||
|
|
||||||
conn._http_vsn = self._http_vsn
|
|
||||||
conn._http_vsn_str = self._http_vsn_str
|
|
||||||
|
|
||||||
self.file = None
|
|
||||||
|
|
||||||
def connect(self, host=None, port=None):
|
|
||||||
"Accept arguments to set the host/port, since the superclass doesn't."
|
|
||||||
|
|
||||||
if host is not None:
|
|
||||||
self._conn._set_hostport(host, port)
|
|
||||||
self._conn.connect()
|
|
||||||
|
|
||||||
def getfile(self):
|
|
||||||
"Provide a getfile, since the superclass' does not use this concept."
|
|
||||||
return self.file
|
|
||||||
|
|
||||||
def putheader(self, header, *values):
|
|
||||||
"The superclass allows only one value argument."
|
|
||||||
self._conn.putheader(header, '\r\n\t'.join(values))
|
|
||||||
|
|
||||||
def getreply(self):
|
|
||||||
"""Compat definition since superclass does not define it.
|
|
||||||
|
|
||||||
Returns a tuple consisting of:
|
|
||||||
- server status code (e.g. '200' if all goes well)
|
|
||||||
- server "reason" corresponding to status code
|
|
||||||
- any RFC822 headers in the response from the server
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
response = self._conn.getresponse()
|
|
||||||
except BadStatusLine as e:
|
|
||||||
# keep the socket open (as a file), and return it
|
|
||||||
self.file = self._conn.sock.makefile('rb', 0)
|
|
||||||
|
|
||||||
# close our socket -- we want to restart after any protocol error
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
self.headers = None
|
|
||||||
return -1, e.line, None
|
|
||||||
|
|
||||||
self.headers = response.msg
|
|
||||||
self.file = response.fp
|
|
||||||
return response.status, response.reason, response.msg
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self._conn.close()
|
|
||||||
|
|
||||||
# note that self.file == response.fp, which gets closed by the
|
|
||||||
# superclass. just clear the object ref here.
|
|
||||||
### hmm. messy. if status==-1, then self.file is owned by us.
|
|
||||||
### well... we aren't explicitly closing, but losing this ref will
|
|
||||||
### do it
|
|
||||||
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
|
|
||||||
|
|
||||||
def __init__(self, host='', port=None, key_file=None, cert_file=None,
|
|
||||||
strict=None):
|
|
||||||
# provide a default host, pass the X509 cert info
|
|
||||||
|
|
||||||
# urf. compensate for bad input.
|
|
||||||
if port == 0:
|
|
||||||
port = None
|
|
||||||
self._setup(self._connection_class(host, port, key_file,
|
|
||||||
cert_file, strict))
|
|
||||||
|
|
||||||
# we never actually use these for anything, but we keep them
|
|
||||||
# here for compatibility with post-1.5.2 CVS.
|
|
||||||
self.key_file = key_file
|
|
||||||
self.cert_file = cert_file
|
|
||||||
|
|
||||||
|
|
||||||
class HTTPException(Exception):
|
class HTTPException(Exception):
|
||||||
# Subclasses that define an __init__ must call Exception.__init__
|
# Subclasses that define an __init__ must call Exception.__init__
|
||||||
# or define self.args. Otherwise, str() will fail.
|
# or define self.args. Otherwise, str() will fail.
|
||||||
|
|
@ -1392,67 +1280,3 @@ class LineAndFileWrapper:
|
||||||
return L + self._file.readlines()
|
return L + self._file.readlines()
|
||||||
else:
|
else:
|
||||||
return L + self._file.readlines(size)
|
return L + self._file.readlines(size)
|
||||||
|
|
||||||
def test():
|
|
||||||
"""Test this module.
|
|
||||||
|
|
||||||
A hodge podge of tests collected here, because they have too many
|
|
||||||
external dependencies for the regular test suite.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import getopt
|
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'd')
|
|
||||||
dl = 0
|
|
||||||
for o, a in opts:
|
|
||||||
if o == '-d': dl = dl + 1
|
|
||||||
host = 'www.python.org'
|
|
||||||
selector = '/'
|
|
||||||
if args[0:]: host = args[0]
|
|
||||||
if args[1:]: selector = args[1]
|
|
||||||
h = HTTP()
|
|
||||||
h.set_debuglevel(dl)
|
|
||||||
h.connect(host)
|
|
||||||
h.putrequest('GET', selector)
|
|
||||||
h.endheaders()
|
|
||||||
status, reason, headers = h.getreply()
|
|
||||||
print('status =', status)
|
|
||||||
print('reason =', reason)
|
|
||||||
print('read', len(h.getfile().read()))
|
|
||||||
print()
|
|
||||||
if headers:
|
|
||||||
for header in headers.headers: print(header.strip())
|
|
||||||
print()
|
|
||||||
|
|
||||||
# minimal test that code to extract host from url works
|
|
||||||
class HTTP11(HTTP):
|
|
||||||
_http_vsn = 11
|
|
||||||
_http_vsn_str = 'HTTP/1.1'
|
|
||||||
|
|
||||||
h = HTTP11('www.python.org')
|
|
||||||
h.putrequest('GET', 'http://www.python.org/~jeremy/')
|
|
||||||
h.endheaders()
|
|
||||||
h.getreply()
|
|
||||||
h.close()
|
|
||||||
|
|
||||||
if hasattr(socket, 'ssl'):
|
|
||||||
|
|
||||||
for host, selector in (('sourceforge.net', '/projects/python'),
|
|
||||||
):
|
|
||||||
print("https://%s%s" % (host, selector))
|
|
||||||
hs = HTTPS()
|
|
||||||
hs.set_debuglevel(dl)
|
|
||||||
hs.connect(host)
|
|
||||||
hs.putrequest('GET', selector)
|
|
||||||
hs.endheaders()
|
|
||||||
status, reason, headers = hs.getreply()
|
|
||||||
print('status =', status)
|
|
||||||
print('reason =', reason)
|
|
||||||
print("read", len(hs.getfile().read()))
|
|
||||||
print()
|
|
||||||
if headers:
|
|
||||||
for header in headers.headers: print(header.strip())
|
|
||||||
print()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test()
|
|
||||||
|
|
|
||||||
|
|
@ -94,21 +94,22 @@ class BasicTest(TestCase):
|
||||||
# Check invalid host_port
|
# Check invalid host_port
|
||||||
|
|
||||||
for hp in ("www.python.org:abc", "www.python.org:"):
|
for hp in ("www.python.org:abc", "www.python.org:"):
|
||||||
self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
|
self.assertRaises(httplib.InvalidURL, httplib.HTTPConnection, hp)
|
||||||
|
|
||||||
for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000),
|
for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000",
|
||||||
|
"fe80::207:e9ff:fe9b", 8000),
|
||||||
("www.python.org:80", "www.python.org", 80),
|
("www.python.org:80", "www.python.org", 80),
|
||||||
("www.python.org", "www.python.org", 80),
|
("www.python.org", "www.python.org", 80),
|
||||||
("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
|
("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
|
||||||
http = httplib.HTTP(hp)
|
c = httplib.HTTPConnection(hp)
|
||||||
c = http._conn
|
self.assertEqual(h, c.host)
|
||||||
if h != c.host: self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
|
self.assertEqual(p, c.port)
|
||||||
if p != c.port: self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
|
|
||||||
|
|
||||||
def test_response_headers(self):
|
def test_response_headers(self):
|
||||||
# test response with multiple message headers with the same field name.
|
# test response with multiple message headers with the same field name.
|
||||||
text = ('HTTP/1.1 200 OK\r\n'
|
text = ('HTTP/1.1 200 OK\r\n'
|
||||||
'Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r\n'
|
'Set-Cookie: Customer="WILE_E_COYOTE"; '
|
||||||
|
'Version="1"; Path="/acme"\r\n'
|
||||||
'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
|
'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
|
||||||
' Path="/acme"\r\n'
|
' Path="/acme"\r\n'
|
||||||
'\r\n'
|
'\r\n'
|
||||||
|
|
@ -120,8 +121,7 @@ class BasicTest(TestCase):
|
||||||
r = httplib.HTTPResponse(s)
|
r = httplib.HTTPResponse(s)
|
||||||
r.begin()
|
r.begin()
|
||||||
cookies = r.getheader("Set-Cookie")
|
cookies = r.getheader("Set-Cookie")
|
||||||
if cookies != hdr:
|
self.assertEqual(cookies, hdr)
|
||||||
self.fail("multiple headers not combined properly")
|
|
||||||
|
|
||||||
def test_read_head(self):
|
def test_read_head(self):
|
||||||
# Test that the library doesn't attempt to read any data
|
# Test that the library doesn't attempt to read any data
|
||||||
|
|
@ -138,8 +138,8 @@ class BasicTest(TestCase):
|
||||||
resp.close()
|
resp.close()
|
||||||
|
|
||||||
def test_send_file(self):
|
def test_send_file(self):
|
||||||
expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
|
expected = ('GET /foo HTTP/1.1\r\nHost: example.com\r\n'
|
||||||
'Accept-Encoding: identity\r\nContent-Length:'
|
'Accept-Encoding: identity\r\nContent-Length:')
|
||||||
|
|
||||||
body = open(__file__, 'rb')
|
body = open(__file__, 'rb')
|
||||||
conn = httplib.HTTPConnection('example.com')
|
conn = httplib.HTTPConnection('example.com')
|
||||||
|
|
@ -169,9 +169,9 @@ class TimeoutTest(TestCase):
|
||||||
self.serv = None
|
self.serv = None
|
||||||
|
|
||||||
def testTimeoutAttribute(self):
|
def testTimeoutAttribute(self):
|
||||||
'''This will prove that the timeout gets through
|
# This will prove that the timeout gets through HTTPConnection
|
||||||
HTTPConnection and into the socket.
|
# and into the socket.
|
||||||
'''
|
|
||||||
# default
|
# default
|
||||||
httpConn = httplib.HTTPConnection(HOST, PORT)
|
httpConn = httplib.HTTPConnection(HOST, PORT)
|
||||||
httpConn.connect()
|
httpConn.connect()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue