blob: 035f0b909e811db2eb79ef133ef38f41706ead8a [file] [log] [blame]
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00001import httplib
2import StringIO
Jeremy Hylton121d34a2003-07-08 12:36:58 +00003import sys
Guido van Rossumd8faa362007-04-27 19:54:29 +00004import socket
Jeremy Hylton121d34a2003-07-08 12:36:58 +00005
Jeremy Hylton2c178252004-08-07 16:28:14 +00006from unittest import TestCase
7
8from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00009
10class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000011 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000012 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000013 self.fileclass = fileclass
Thomas Wouters89f507f2006-12-13 04:49:30 +000014 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000015
Jeremy Hylton2c178252004-08-07 16:28:14 +000016 def sendall(self, data):
Thomas Wouters89f507f2006-12-13 04:49:30 +000017 self.data += data
Jeremy Hylton2c178252004-08-07 16:28:14 +000018
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000019 def makefile(self, mode, bufsize=None):
20 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000021 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000022 return self.fileclass(self.text)
23
24class NoEOFStringIO(StringIO.StringIO):
25 """Like StringIO, but raises AssertionError on EOF.
26
27 This is used below to test that httplib doesn't try to read
28 more from the underlying file than it should.
29 """
30 def read(self, n=-1):
31 data = StringIO.StringIO.read(self, n)
32 if data == '':
33 raise AssertionError('caller tried to read past EOF')
34 return data
35
36 def readline(self, length=None):
37 data = StringIO.StringIO.readline(self, length)
38 if data == '':
39 raise AssertionError('caller tried to read past EOF')
40 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000041
Jeremy Hylton2c178252004-08-07 16:28:14 +000042
43class HeaderTests(TestCase):
44 def test_auto_headers(self):
45 # Some headers are added automatically, but should not be added by
46 # .request() if they are explicitly set.
47
48 import httplib
49
50 class HeaderCountingBuffer(list):
51 def __init__(self):
52 self.count = {}
53 def append(self, item):
54 kv = item.split(':')
55 if len(kv) > 1:
56 # item is a 'Key: Value' header string
57 lcKey = kv[0].lower()
58 self.count.setdefault(lcKey, 0)
59 self.count[lcKey] += 1
60 list.append(self, item)
61
62 for explicit_header in True, False:
63 for header in 'Content-length', 'Host', 'Accept-encoding':
64 conn = httplib.HTTPConnection('example.com')
65 conn.sock = FakeSocket('blahblahblah')
66 conn._buffer = HeaderCountingBuffer()
67
68 body = 'spamspamspam'
69 headers = {}
70 if explicit_header:
71 headers[header] = str(len(body))
72 conn.request('POST', '/', body, headers)
73 self.assertEqual(conn._buffer.count[header.lower()], 1)
74
Thomas Wouters89f507f2006-12-13 04:49:30 +000075class BasicTest(TestCase):
76 def test_status_lines(self):
77 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000078
Thomas Wouters89f507f2006-12-13 04:49:30 +000079 body = "HTTP/1.1 200 Ok\r\n\r\nText"
80 sock = FakeSocket(body)
81 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000082 resp.begin()
Thomas Wouters89f507f2006-12-13 04:49:30 +000083 self.assertEqual(resp.read(), 'Text')
84 resp.close()
Jeremy Hyltonba603192003-01-23 18:02:20 +000085
Thomas Wouters89f507f2006-12-13 04:49:30 +000086 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
87 sock = FakeSocket(body)
88 resp = httplib.HTTPResponse(sock)
89 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000090
Thomas Wouters89f507f2006-12-13 04:49:30 +000091 def test_host_port(self):
92 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +000093
Thomas Wouters89f507f2006-12-13 04:49:30 +000094 for hp in ("www.python.org:abc", "www.python.org:"):
95 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
96
97 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000),
98 ("www.python.org:80", "www.python.org", 80),
99 ("www.python.org", "www.python.org", 80),
100 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000101 http = httplib.HTTP(hp)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000102 c = http._conn
103 if h != c.host: self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
104 if p != c.port: self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000105
Thomas Wouters89f507f2006-12-13 04:49:30 +0000106 def test_response_headers(self):
107 # test response with multiple message headers with the same field name.
108 text = ('HTTP/1.1 200 OK\r\n'
109 'Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r\n'
110 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
111 ' Path="/acme"\r\n'
112 '\r\n'
113 'No body\r\n')
114 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
115 ', '
116 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
117 s = FakeSocket(text)
118 r = httplib.HTTPResponse(s)
119 r.begin()
120 cookies = r.getheader("Set-Cookie")
121 if cookies != hdr:
122 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000123
Thomas Wouters89f507f2006-12-13 04:49:30 +0000124 def test_read_head(self):
125 # Test that the library doesn't attempt to read any data
126 # from a HEAD request. (Tickles SF bug #622042.)
127 sock = FakeSocket(
128 'HTTP/1.1 200 OK\r\n'
129 'Content-Length: 14432\r\n'
130 '\r\n',
131 NoEOFStringIO)
132 resp = httplib.HTTPResponse(sock, method="HEAD")
133 resp.begin()
134 if resp.read() != "":
135 self.fail("Did not expect response from HEAD request")
136 resp.close()
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000137
Thomas Wouters89f507f2006-12-13 04:49:30 +0000138 def test_send_file(self):
139 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
140 'Accept-Encoding: identity\r\nContent-Length:'
141
142 body = open(__file__, 'rb')
143 conn = httplib.HTTPConnection('example.com')
144 sock = FakeSocket(body)
145 conn.sock = sock
146 conn.request('GET', '/foo', body)
147 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000148
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000149class OfflineTest(TestCase):
150 def test_responses(self):
151 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
152
Guido van Rossumd8faa362007-04-27 19:54:29 +0000153PORT = 50003
154HOST = "localhost"
155
156class TimeoutTest(TestCase):
157
158 def setUp(self):
159 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
160 self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
161 global PORT
162 PORT = test_support.bind_port(self.serv, HOST, PORT)
163 self.serv.listen(5)
164
165 def tearDown(self):
166 self.serv.close()
167 self.serv = None
168
169 def testTimeoutAttribute(self):
170 '''This will prove that the timeout gets through
171 HTTPConnection and into the socket.
172 '''
173 # default
174 httpConn = httplib.HTTPConnection(HOST, PORT)
175 httpConn.connect()
176 self.assertTrue(httpConn.sock.gettimeout() is None)
177 httpConn.close()
178
179 # a value
180 httpConn = httplib.HTTPConnection(HOST, PORT, timeout=30)
181 httpConn.connect()
182 self.assertEqual(httpConn.sock.gettimeout(), 30)
183 httpConn.close()
184
185 # None, having other default
186 previous = socket.getdefaulttimeout()
187 socket.setdefaulttimeout(30)
188 try:
189 httpConn = httplib.HTTPConnection(HOST, PORT, timeout=None)
190 httpConn.connect()
191 finally:
192 socket.setdefaulttimeout(previous)
193 self.assertEqual(httpConn.sock.gettimeout(), 30)
194 httpConn.close()
195
196
Jeremy Hylton2c178252004-08-07 16:28:14 +0000197def test_main(verbose=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000198 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000199
Thomas Wouters89f507f2006-12-13 04:49:30 +0000200if __name__ == '__main__':
201 test_main()