blob: 77e9887cc58d89f570d7672173e70cc38d468658 [file] [log] [blame]
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00001import httplib
2import StringIO
Facundo Batista07c78be2007-03-23 18:54:07 +00003import socket
Jeremy Hylton121d34a2003-07-08 12:36:58 +00004
Jeremy Hylton2c178252004-08-07 16:28:14 +00005from unittest import TestCase
6
7from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00008
Trent Nelsone41b0062008-04-08 23:47:30 +00009HOST = test_support.HOST
10
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000011class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000012 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000013 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000014 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000015 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000016
Jeremy Hylton2c178252004-08-07 16:28:14 +000017 def sendall(self, data):
Martin v. Löwis040a9272006-11-12 10:32:47 +000018 self.data += data
Jeremy Hylton2c178252004-08-07 16:28:14 +000019
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000020 def makefile(self, mode, bufsize=None):
21 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000022 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000023 return self.fileclass(self.text)
24
25class NoEOFStringIO(StringIO.StringIO):
26 """Like StringIO, but raises AssertionError on EOF.
27
28 This is used below to test that httplib doesn't try to read
29 more from the underlying file than it should.
30 """
31 def read(self, n=-1):
32 data = StringIO.StringIO.read(self, n)
33 if data == '':
34 raise AssertionError('caller tried to read past EOF')
35 return data
36
37 def readline(self, length=None):
38 data = StringIO.StringIO.readline(self, length)
39 if data == '':
40 raise AssertionError('caller tried to read past EOF')
41 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000042
Jeremy Hylton2c178252004-08-07 16:28:14 +000043
44class HeaderTests(TestCase):
45 def test_auto_headers(self):
46 # Some headers are added automatically, but should not be added by
47 # .request() if they are explicitly set.
48
49 import httplib
50
51 class HeaderCountingBuffer(list):
52 def __init__(self):
53 self.count = {}
54 def append(self, item):
55 kv = item.split(':')
56 if len(kv) > 1:
57 # item is a 'Key: Value' header string
58 lcKey = kv[0].lower()
59 self.count.setdefault(lcKey, 0)
60 self.count[lcKey] += 1
61 list.append(self, item)
62
63 for explicit_header in True, False:
64 for header in 'Content-length', 'Host', 'Accept-encoding':
65 conn = httplib.HTTPConnection('example.com')
66 conn.sock = FakeSocket('blahblahblah')
67 conn._buffer = HeaderCountingBuffer()
68
69 body = 'spamspamspam'
70 headers = {}
71 if explicit_header:
72 headers[header] = str(len(body))
73 conn.request('POST', '/', body, headers)
74 self.assertEqual(conn._buffer.count[header.lower()], 1)
75
Georg Brandl71a20892006-10-29 20:24:01 +000076class BasicTest(TestCase):
77 def test_status_lines(self):
78 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000079
Georg Brandl71a20892006-10-29 20:24:01 +000080 body = "HTTP/1.1 200 Ok\r\n\r\nText"
81 sock = FakeSocket(body)
82 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000083 resp.begin()
Georg Brandl71a20892006-10-29 20:24:01 +000084 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +000085 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000086
Georg Brandl71a20892006-10-29 20:24:01 +000087 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
88 sock = FakeSocket(body)
89 resp = httplib.HTTPResponse(sock)
90 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000091
Facundo Batista70665902007-10-18 03:16:03 +000092 def test_partial_reads(self):
93 # if we have a lenght, the system knows when to close itself
94 # same behaviour than when we read the whole thing with read()
95 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
96 sock = FakeSocket(body)
97 resp = httplib.HTTPResponse(sock)
98 resp.begin()
99 self.assertEqual(resp.read(2), 'Te')
100 self.assertFalse(resp.isclosed())
101 self.assertEqual(resp.read(2), 'xt')
102 self.assertTrue(resp.isclosed())
103
Georg Brandl71a20892006-10-29 20:24:01 +0000104 def test_host_port(self):
105 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000106
Georg Brandl71a20892006-10-29 20:24:01 +0000107 for hp in ("www.python.org:abc", "www.python.org:"):
108 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
109
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000110 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
111 8000),
Georg Brandl71a20892006-10-29 20:24:01 +0000112 ("www.python.org:80", "www.python.org", 80),
113 ("www.python.org", "www.python.org", 80),
114 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000115 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000116 c = http._conn
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000117 if h != c.host:
118 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
119 if p != c.port:
120 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000121
Georg Brandl71a20892006-10-29 20:24:01 +0000122 def test_response_headers(self):
123 # test response with multiple message headers with the same field name.
124 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000125 'Set-Cookie: Customer="WILE_E_COYOTE";'
126 ' Version="1"; Path="/acme"\r\n'
Georg Brandl71a20892006-10-29 20:24:01 +0000127 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
128 ' Path="/acme"\r\n'
129 '\r\n'
130 'No body\r\n')
131 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
132 ', '
133 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
134 s = FakeSocket(text)
135 r = httplib.HTTPResponse(s)
136 r.begin()
137 cookies = r.getheader("Set-Cookie")
138 if cookies != hdr:
139 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000140
Georg Brandl71a20892006-10-29 20:24:01 +0000141 def test_read_head(self):
142 # Test that the library doesn't attempt to read any data
143 # from a HEAD request. (Tickles SF bug #622042.)
144 sock = FakeSocket(
145 'HTTP/1.1 200 OK\r\n'
146 'Content-Length: 14432\r\n'
147 '\r\n',
148 NoEOFStringIO)
149 resp = httplib.HTTPResponse(sock, method="HEAD")
150 resp.begin()
151 if resp.read() != "":
152 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000153
Martin v. Löwis040a9272006-11-12 10:32:47 +0000154 def test_send_file(self):
155 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
156 'Accept-Encoding: identity\r\nContent-Length:'
157
158 body = open(__file__, 'rb')
159 conn = httplib.HTTPConnection('example.com')
160 sock = FakeSocket(body)
161 conn.sock = sock
162 conn.request('GET', '/foo', body)
163 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000164
Georg Brandl23635032008-02-24 00:03:22 +0000165 def test_chunked(self):
166 chunked_start = (
167 'HTTP/1.1 200 OK\r\n'
168 'Transfer-Encoding: chunked\r\n\r\n'
169 'a\r\n'
170 'hello worl\r\n'
171 '1\r\n'
172 'd\r\n'
173 )
174 sock = FakeSocket(chunked_start + '0\r\n')
175 resp = httplib.HTTPResponse(sock, method="GET")
176 resp.begin()
177 self.assertEquals(resp.read(), 'hello world')
178 resp.close()
179
180 for x in ('', 'foo\r\n'):
181 sock = FakeSocket(chunked_start + x)
182 resp = httplib.HTTPResponse(sock, method="GET")
183 resp.begin()
184 try:
185 resp.read()
186 except httplib.IncompleteRead, i:
187 self.assertEquals(i.partial, 'hello world')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000188 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
189 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000190 else:
191 self.fail('IncompleteRead expected')
192 finally:
193 resp.close()
194
Georg Brandl8c460d52008-02-24 00:14:24 +0000195 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000196 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
197 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000198 resp = httplib.HTTPResponse(sock, method="GET")
199 resp.begin()
200 self.assertEquals(resp.read(), 'Hello\r\n')
201 resp.close()
202
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000203 def test_incomplete_read(self):
204 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
205 resp = httplib.HTTPResponse(sock, method="GET")
206 resp.begin()
207 try:
208 resp.read()
209 except httplib.IncompleteRead as i:
210 self.assertEquals(i.partial, 'Hello\r\n')
211 self.assertEqual(repr(i),
212 "IncompleteRead(7 bytes read, 3 more expected)")
213 self.assertEqual(str(i),
214 "IncompleteRead(7 bytes read, 3 more expected)")
215 else:
216 self.fail('IncompleteRead expected')
217 finally:
218 resp.close()
219
Georg Brandl23635032008-02-24 00:03:22 +0000220
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000221class OfflineTest(TestCase):
222 def test_responses(self):
223 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
224
Facundo Batista07c78be2007-03-23 18:54:07 +0000225class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000226 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000227
Facundo Batista07c78be2007-03-23 18:54:07 +0000228 def setUp(self):
229 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000230 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000231 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000232
233 def tearDown(self):
234 self.serv.close()
235 self.serv = None
236
237 def testTimeoutAttribute(self):
238 '''This will prove that the timeout gets through
239 HTTPConnection and into the socket.
240 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000241 # default -- use global socket timeout
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000242 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000243 socket.setdefaulttimeout(30)
244 try:
245 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
246 httpConn.connect()
247 finally:
248 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000249 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000250 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000251
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000252 # no timeout -- do not use global socket default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000253 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000254 socket.setdefaulttimeout(30)
255 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000256 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
257 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000258 httpConn.connect()
259 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000260 socket.setdefaulttimeout(None)
261 self.assertEqual(httpConn.sock.gettimeout(), None)
262 httpConn.close()
263
264 # a value
265 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
266 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000267 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000268 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000269
270
Facundo Batista70f996b2007-05-21 17:32:32 +0000271class HTTPSTimeoutTest(TestCase):
272# XXX Here should be tests for HTTPS, there isn't any right now!
273
274 def test_attributes(self):
275 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000276 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000277 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000278 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000279
Jeremy Hylton2c178252004-08-07 16:28:14 +0000280def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000281 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
282 HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000283
Georg Brandl71a20892006-10-29 20:24:01 +0000284if __name__ == '__main__':
285 test_main()