blob: 2d0b8e750bd7ef9911cc0795371f10f77dd5b5d5 [file] [log] [blame]
Antoine Pitrou72481782009-09-29 17:48:18 +00001import array
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00002import httplib
3import StringIO
Facundo Batista07c78be2007-03-23 18:54:07 +00004import socket
Jeremy Hylton121d34a2003-07-08 12:36:58 +00005
Gregory P. Smith9d325212010-01-03 02:06:07 +00006import unittest
7TestCase = unittest.TestCase
Jeremy Hylton2c178252004-08-07 16:28:14 +00008
9from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000010
Trent Nelsone41b0062008-04-08 23:47:30 +000011HOST = test_support.HOST
12
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000013class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000014 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000015 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000016 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000017 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000018
Jeremy Hylton2c178252004-08-07 16:28:14 +000019 def sendall(self, data):
Antoine Pitrou72481782009-09-29 17:48:18 +000020 self.data += ''.join(data)
Jeremy Hylton2c178252004-08-07 16:28:14 +000021
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000022 def makefile(self, mode, bufsize=None):
23 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000024 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000025 return self.fileclass(self.text)
26
27class NoEOFStringIO(StringIO.StringIO):
28 """Like StringIO, but raises AssertionError on EOF.
29
30 This is used below to test that httplib doesn't try to read
31 more from the underlying file than it should.
32 """
33 def read(self, n=-1):
34 data = StringIO.StringIO.read(self, n)
35 if data == '':
36 raise AssertionError('caller tried to read past EOF')
37 return data
38
39 def readline(self, length=None):
40 data = StringIO.StringIO.readline(self, length)
41 if data == '':
42 raise AssertionError('caller tried to read past EOF')
43 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000044
Jeremy Hylton2c178252004-08-07 16:28:14 +000045
46class HeaderTests(TestCase):
47 def test_auto_headers(self):
48 # Some headers are added automatically, but should not be added by
49 # .request() if they are explicitly set.
50
51 import httplib
52
53 class HeaderCountingBuffer(list):
54 def __init__(self):
55 self.count = {}
56 def append(self, item):
57 kv = item.split(':')
58 if len(kv) > 1:
59 # item is a 'Key: Value' header string
60 lcKey = kv[0].lower()
61 self.count.setdefault(lcKey, 0)
62 self.count[lcKey] += 1
63 list.append(self, item)
64
65 for explicit_header in True, False:
66 for header in 'Content-length', 'Host', 'Accept-encoding':
67 conn = httplib.HTTPConnection('example.com')
68 conn.sock = FakeSocket('blahblahblah')
69 conn._buffer = HeaderCountingBuffer()
70
71 body = 'spamspamspam'
72 headers = {}
73 if explicit_header:
74 headers[header] = str(len(body))
75 conn.request('POST', '/', body, headers)
76 self.assertEqual(conn._buffer.count[header.lower()], 1)
77
Georg Brandl71a20892006-10-29 20:24:01 +000078class BasicTest(TestCase):
79 def test_status_lines(self):
80 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000081
Georg Brandl71a20892006-10-29 20:24:01 +000082 body = "HTTP/1.1 200 Ok\r\n\r\nText"
83 sock = FakeSocket(body)
84 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000085 resp.begin()
Georg Brandl71a20892006-10-29 20:24:01 +000086 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +000087 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000088
Georg Brandl71a20892006-10-29 20:24:01 +000089 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
90 sock = FakeSocket(body)
91 resp = httplib.HTTPResponse(sock)
92 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000093
Dirkjan Ochtmanebc73dc2010-02-24 04:49:00 +000094 def test_bad_status_repr(self):
95 exc = httplib.BadStatusLine('')
96 self.assertEquals(repr(exc), '''BadStatusLine("\'\'",)''')
97
Facundo Batista70665902007-10-18 03:16:03 +000098 def test_partial_reads(self):
99 # if we have a lenght, the system knows when to close itself
100 # same behaviour than when we read the whole thing with read()
101 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
102 sock = FakeSocket(body)
103 resp = httplib.HTTPResponse(sock)
104 resp.begin()
105 self.assertEqual(resp.read(2), 'Te')
106 self.assertFalse(resp.isclosed())
107 self.assertEqual(resp.read(2), 'xt')
108 self.assertTrue(resp.isclosed())
109
Georg Brandl71a20892006-10-29 20:24:01 +0000110 def test_host_port(self):
111 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000112
Georg Brandl71a20892006-10-29 20:24:01 +0000113 for hp in ("www.python.org:abc", "www.python.org:"):
114 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
115
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000116 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
117 8000),
Georg Brandl71a20892006-10-29 20:24:01 +0000118 ("www.python.org:80", "www.python.org", 80),
119 ("www.python.org", "www.python.org", 80),
120 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000121 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000122 c = http._conn
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000123 if h != c.host:
124 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
125 if p != c.port:
126 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000127
Georg Brandl71a20892006-10-29 20:24:01 +0000128 def test_response_headers(self):
129 # test response with multiple message headers with the same field name.
130 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000131 'Set-Cookie: Customer="WILE_E_COYOTE";'
132 ' Version="1"; Path="/acme"\r\n'
Georg Brandl71a20892006-10-29 20:24:01 +0000133 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
134 ' Path="/acme"\r\n'
135 '\r\n'
136 'No body\r\n')
137 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
138 ', '
139 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
140 s = FakeSocket(text)
141 r = httplib.HTTPResponse(s)
142 r.begin()
143 cookies = r.getheader("Set-Cookie")
144 if cookies != hdr:
145 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000146
Georg Brandl71a20892006-10-29 20:24:01 +0000147 def test_read_head(self):
148 # Test that the library doesn't attempt to read any data
149 # from a HEAD request. (Tickles SF bug #622042.)
150 sock = FakeSocket(
151 'HTTP/1.1 200 OK\r\n'
152 'Content-Length: 14432\r\n'
153 '\r\n',
154 NoEOFStringIO)
155 resp = httplib.HTTPResponse(sock, method="HEAD")
156 resp.begin()
157 if resp.read() != "":
158 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000159
Martin v. Löwis040a9272006-11-12 10:32:47 +0000160 def test_send_file(self):
161 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
162 'Accept-Encoding: identity\r\nContent-Length:'
163
164 body = open(__file__, 'rb')
165 conn = httplib.HTTPConnection('example.com')
166 sock = FakeSocket(body)
167 conn.sock = sock
168 conn.request('GET', '/foo', body)
169 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000170
Antoine Pitrou72481782009-09-29 17:48:18 +0000171 def test_send(self):
172 expected = 'this is a test this is only a test'
173 conn = httplib.HTTPConnection('example.com')
174 sock = FakeSocket(None)
175 conn.sock = sock
176 conn.send(expected)
177 self.assertEquals(expected, sock.data)
178 sock.data = ''
179 conn.send(array.array('c', expected))
180 self.assertEquals(expected, sock.data)
181 sock.data = ''
182 conn.send(StringIO.StringIO(expected))
183 self.assertEquals(expected, sock.data)
184
Georg Brandl23635032008-02-24 00:03:22 +0000185 def test_chunked(self):
186 chunked_start = (
187 'HTTP/1.1 200 OK\r\n'
188 'Transfer-Encoding: chunked\r\n\r\n'
189 'a\r\n'
190 'hello worl\r\n'
191 '1\r\n'
192 'd\r\n'
193 )
194 sock = FakeSocket(chunked_start + '0\r\n')
195 resp = httplib.HTTPResponse(sock, method="GET")
196 resp.begin()
197 self.assertEquals(resp.read(), 'hello world')
198 resp.close()
199
200 for x in ('', 'foo\r\n'):
201 sock = FakeSocket(chunked_start + x)
202 resp = httplib.HTTPResponse(sock, method="GET")
203 resp.begin()
204 try:
205 resp.read()
206 except httplib.IncompleteRead, i:
207 self.assertEquals(i.partial, 'hello world')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000208 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
209 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000210 else:
211 self.fail('IncompleteRead expected')
212 finally:
213 resp.close()
214
Senthil Kumaraned9204342010-04-28 17:20:43 +0000215 def test_chunked_head(self):
216 chunked_start = (
217 'HTTP/1.1 200 OK\r\n'
218 'Transfer-Encoding: chunked\r\n\r\n'
219 'a\r\n'
220 'hello world\r\n'
221 '1\r\n'
222 'd\r\n'
223 )
224 sock = FakeSocket(chunked_start + '0\r\n')
225 resp = httplib.HTTPResponse(sock, method="HEAD")
226 resp.begin()
227 self.assertEquals(resp.read(), '')
228 self.assertEquals(resp.status, 200)
229 self.assertEquals(resp.reason, 'OK')
Senthil Kumaranfb695012010-06-04 17:17:09 +0000230 self.assertTrue(resp.isclosed())
Senthil Kumaraned9204342010-04-28 17:20:43 +0000231
Georg Brandl8c460d52008-02-24 00:14:24 +0000232 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000233 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
234 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000235 resp = httplib.HTTPResponse(sock, method="GET")
236 resp.begin()
237 self.assertEquals(resp.read(), 'Hello\r\n')
238 resp.close()
239
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000240 def test_incomplete_read(self):
241 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
242 resp = httplib.HTTPResponse(sock, method="GET")
243 resp.begin()
244 try:
245 resp.read()
246 except httplib.IncompleteRead as i:
247 self.assertEquals(i.partial, 'Hello\r\n')
248 self.assertEqual(repr(i),
249 "IncompleteRead(7 bytes read, 3 more expected)")
250 self.assertEqual(str(i),
251 "IncompleteRead(7 bytes read, 3 more expected)")
252 else:
253 self.fail('IncompleteRead expected')
254 finally:
255 resp.close()
256
Georg Brandl23635032008-02-24 00:03:22 +0000257
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000258class OfflineTest(TestCase):
259 def test_responses(self):
260 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
261
Gregory P. Smith9d325212010-01-03 02:06:07 +0000262
263class SourceAddressTest(TestCase):
264 def setUp(self):
265 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
266 self.port = test_support.bind_port(self.serv)
267 self.source_port = test_support.find_unused_port()
268 self.serv.listen(5)
269 self.conn = None
270
271 def tearDown(self):
272 if self.conn:
273 self.conn.close()
274 self.conn = None
275 self.serv.close()
276 self.serv = None
277
278 def testHTTPConnectionSourceAddress(self):
279 self.conn = httplib.HTTPConnection(HOST, self.port,
280 source_address=('', self.source_port))
281 self.conn.connect()
282 self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
283
284 @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
285 'httplib.HTTPSConnection not defined')
286 def testHTTPSConnectionSourceAddress(self):
287 self.conn = httplib.HTTPSConnection(HOST, self.port,
288 source_address=('', self.source_port))
289 # We don't test anything here other the constructor not barfing as
290 # this code doesn't deal with setting up an active running SSL server
291 # for an ssl_wrapped connect() to actually return from.
292
293
Facundo Batista07c78be2007-03-23 18:54:07 +0000294class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000295 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000296
Facundo Batista07c78be2007-03-23 18:54:07 +0000297 def setUp(self):
298 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000299 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000300 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000301
302 def tearDown(self):
303 self.serv.close()
304 self.serv = None
305
306 def testTimeoutAttribute(self):
307 '''This will prove that the timeout gets through
308 HTTPConnection and into the socket.
309 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000310 # default -- use global socket timeout
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000311 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000312 socket.setdefaulttimeout(30)
313 try:
314 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
315 httpConn.connect()
316 finally:
317 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000318 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000319 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000320
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000321 # no timeout -- do not use global socket default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000322 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000323 socket.setdefaulttimeout(30)
324 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000325 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
326 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000327 httpConn.connect()
328 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000329 socket.setdefaulttimeout(None)
330 self.assertEqual(httpConn.sock.gettimeout(), None)
331 httpConn.close()
332
333 # a value
334 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
335 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000336 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000337 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000338
339
Facundo Batista70f996b2007-05-21 17:32:32 +0000340class HTTPSTimeoutTest(TestCase):
341# XXX Here should be tests for HTTPS, there isn't any right now!
342
343 def test_attributes(self):
344 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000345 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000346 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000347 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000348
Jeremy Hylton2c178252004-08-07 16:28:14 +0000349def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000350 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Gregory P. Smith9d325212010-01-03 02:06:07 +0000351 HTTPSTimeoutTest, SourceAddressTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000352
Georg Brandl71a20892006-10-29 20:24:01 +0000353if __name__ == '__main__':
354 test_main()