blob: 435a9fc8b81b93340efb977fe195182554248b35 [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
Victor Stinner2c6aee92010-07-24 02:46:16 +00005import errno
Jeremy Hylton121d34a2003-07-08 12:36:58 +00006
Gregory P. Smith9d325212010-01-03 02:06:07 +00007import unittest
8TestCase = unittest.TestCase
Jeremy Hylton2c178252004-08-07 16:28:14 +00009
10from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000011
Trent Nelsone41b0062008-04-08 23:47:30 +000012HOST = test_support.HOST
13
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000014class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000015 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000016 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000017 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000018 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000019
Jeremy Hylton2c178252004-08-07 16:28:14 +000020 def sendall(self, data):
Antoine Pitrou72481782009-09-29 17:48:18 +000021 self.data += ''.join(data)
Jeremy Hylton2c178252004-08-07 16:28:14 +000022
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000023 def makefile(self, mode, bufsize=None):
24 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000025 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000026 return self.fileclass(self.text)
27
Victor Stinner2c6aee92010-07-24 02:46:16 +000028class EPipeSocket(FakeSocket):
29
30 def __init__(self, text, pipe_trigger):
31 # When sendall() is called with pipe_trigger, raise EPIPE.
32 FakeSocket.__init__(self, text)
33 self.pipe_trigger = pipe_trigger
34
35 def sendall(self, data):
36 if self.pipe_trigger in data:
37 raise socket.error(errno.EPIPE, "gotcha")
38 self.data += data
39
40 def close(self):
41 pass
42
Jeremy Hylton121d34a2003-07-08 12:36:58 +000043class NoEOFStringIO(StringIO.StringIO):
44 """Like StringIO, but raises AssertionError on EOF.
45
46 This is used below to test that httplib doesn't try to read
47 more from the underlying file than it should.
48 """
49 def read(self, n=-1):
50 data = StringIO.StringIO.read(self, n)
51 if data == '':
52 raise AssertionError('caller tried to read past EOF')
53 return data
54
55 def readline(self, length=None):
56 data = StringIO.StringIO.readline(self, length)
57 if data == '':
58 raise AssertionError('caller tried to read past EOF')
59 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000060
Jeremy Hylton2c178252004-08-07 16:28:14 +000061
62class HeaderTests(TestCase):
63 def test_auto_headers(self):
64 # Some headers are added automatically, but should not be added by
65 # .request() if they are explicitly set.
66
67 import httplib
68
69 class HeaderCountingBuffer(list):
70 def __init__(self):
71 self.count = {}
72 def append(self, item):
73 kv = item.split(':')
74 if len(kv) > 1:
75 # item is a 'Key: Value' header string
76 lcKey = kv[0].lower()
77 self.count.setdefault(lcKey, 0)
78 self.count[lcKey] += 1
79 list.append(self, item)
80
81 for explicit_header in True, False:
82 for header in 'Content-length', 'Host', 'Accept-encoding':
83 conn = httplib.HTTPConnection('example.com')
84 conn.sock = FakeSocket('blahblahblah')
85 conn._buffer = HeaderCountingBuffer()
86
87 body = 'spamspamspam'
88 headers = {}
89 if explicit_header:
90 headers[header] = str(len(body))
91 conn.request('POST', '/', body, headers)
92 self.assertEqual(conn._buffer.count[header.lower()], 1)
93
Georg Brandl71a20892006-10-29 20:24:01 +000094class BasicTest(TestCase):
95 def test_status_lines(self):
96 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000097
Georg Brandl71a20892006-10-29 20:24:01 +000098 body = "HTTP/1.1 200 Ok\r\n\r\nText"
99 sock = FakeSocket(body)
100 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000101 resp.begin()
Georg Brandl71a20892006-10-29 20:24:01 +0000102 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +0000103 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +0000104
Georg Brandl71a20892006-10-29 20:24:01 +0000105 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
106 sock = FakeSocket(body)
107 resp = httplib.HTTPResponse(sock)
108 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000109
Dirkjan Ochtmanebc73dc2010-02-24 04:49:00 +0000110 def test_bad_status_repr(self):
111 exc = httplib.BadStatusLine('')
112 self.assertEquals(repr(exc), '''BadStatusLine("\'\'",)''')
113
Facundo Batista70665902007-10-18 03:16:03 +0000114 def test_partial_reads(self):
115 # if we have a lenght, the system knows when to close itself
116 # same behaviour than when we read the whole thing with read()
117 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
118 sock = FakeSocket(body)
119 resp = httplib.HTTPResponse(sock)
120 resp.begin()
121 self.assertEqual(resp.read(2), 'Te')
122 self.assertFalse(resp.isclosed())
123 self.assertEqual(resp.read(2), 'xt')
124 self.assertTrue(resp.isclosed())
125
Georg Brandl71a20892006-10-29 20:24:01 +0000126 def test_host_port(self):
127 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000128
Georg Brandl71a20892006-10-29 20:24:01 +0000129 for hp in ("www.python.org:abc", "www.python.org:"):
130 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
131
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000132 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
133 8000),
Georg Brandl71a20892006-10-29 20:24:01 +0000134 ("www.python.org:80", "www.python.org", 80),
135 ("www.python.org", "www.python.org", 80),
136 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000137 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000138 c = http._conn
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000139 if h != c.host:
140 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
141 if p != c.port:
142 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000143
Georg Brandl71a20892006-10-29 20:24:01 +0000144 def test_response_headers(self):
145 # test response with multiple message headers with the same field name.
146 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000147 'Set-Cookie: Customer="WILE_E_COYOTE";'
148 ' Version="1"; Path="/acme"\r\n'
Georg Brandl71a20892006-10-29 20:24:01 +0000149 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
150 ' Path="/acme"\r\n'
151 '\r\n'
152 'No body\r\n')
153 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
154 ', '
155 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
156 s = FakeSocket(text)
157 r = httplib.HTTPResponse(s)
158 r.begin()
159 cookies = r.getheader("Set-Cookie")
160 if cookies != hdr:
161 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000162
Georg Brandl71a20892006-10-29 20:24:01 +0000163 def test_read_head(self):
164 # Test that the library doesn't attempt to read any data
165 # from a HEAD request. (Tickles SF bug #622042.)
166 sock = FakeSocket(
167 'HTTP/1.1 200 OK\r\n'
168 'Content-Length: 14432\r\n'
169 '\r\n',
170 NoEOFStringIO)
171 resp = httplib.HTTPResponse(sock, method="HEAD")
172 resp.begin()
173 if resp.read() != "":
174 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000175
Martin v. Löwis040a9272006-11-12 10:32:47 +0000176 def test_send_file(self):
177 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
178 'Accept-Encoding: identity\r\nContent-Length:'
179
180 body = open(__file__, 'rb')
181 conn = httplib.HTTPConnection('example.com')
182 sock = FakeSocket(body)
183 conn.sock = sock
184 conn.request('GET', '/foo', body)
185 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000186
Antoine Pitrou72481782009-09-29 17:48:18 +0000187 def test_send(self):
188 expected = 'this is a test this is only a test'
189 conn = httplib.HTTPConnection('example.com')
190 sock = FakeSocket(None)
191 conn.sock = sock
192 conn.send(expected)
193 self.assertEquals(expected, sock.data)
194 sock.data = ''
195 conn.send(array.array('c', expected))
196 self.assertEquals(expected, sock.data)
197 sock.data = ''
198 conn.send(StringIO.StringIO(expected))
199 self.assertEquals(expected, sock.data)
200
Georg Brandl23635032008-02-24 00:03:22 +0000201 def test_chunked(self):
202 chunked_start = (
203 'HTTP/1.1 200 OK\r\n'
204 'Transfer-Encoding: chunked\r\n\r\n'
205 'a\r\n'
206 'hello worl\r\n'
207 '1\r\n'
208 'd\r\n'
209 )
210 sock = FakeSocket(chunked_start + '0\r\n')
211 resp = httplib.HTTPResponse(sock, method="GET")
212 resp.begin()
213 self.assertEquals(resp.read(), 'hello world')
214 resp.close()
215
216 for x in ('', 'foo\r\n'):
217 sock = FakeSocket(chunked_start + x)
218 resp = httplib.HTTPResponse(sock, method="GET")
219 resp.begin()
220 try:
221 resp.read()
222 except httplib.IncompleteRead, i:
223 self.assertEquals(i.partial, 'hello world')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000224 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
225 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000226 else:
227 self.fail('IncompleteRead expected')
228 finally:
229 resp.close()
230
Senthil Kumaraned9204342010-04-28 17:20:43 +0000231 def test_chunked_head(self):
232 chunked_start = (
233 'HTTP/1.1 200 OK\r\n'
234 'Transfer-Encoding: chunked\r\n\r\n'
235 'a\r\n'
236 'hello world\r\n'
237 '1\r\n'
238 'd\r\n'
239 )
240 sock = FakeSocket(chunked_start + '0\r\n')
241 resp = httplib.HTTPResponse(sock, method="HEAD")
242 resp.begin()
243 self.assertEquals(resp.read(), '')
244 self.assertEquals(resp.status, 200)
245 self.assertEquals(resp.reason, 'OK')
Senthil Kumaranfb695012010-06-04 17:17:09 +0000246 self.assertTrue(resp.isclosed())
Senthil Kumaraned9204342010-04-28 17:20:43 +0000247
Georg Brandl8c460d52008-02-24 00:14:24 +0000248 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000249 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
250 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000251 resp = httplib.HTTPResponse(sock, method="GET")
252 resp.begin()
253 self.assertEquals(resp.read(), 'Hello\r\n')
254 resp.close()
255
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000256 def test_incomplete_read(self):
257 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
258 resp = httplib.HTTPResponse(sock, method="GET")
259 resp.begin()
260 try:
261 resp.read()
262 except httplib.IncompleteRead as i:
263 self.assertEquals(i.partial, 'Hello\r\n')
264 self.assertEqual(repr(i),
265 "IncompleteRead(7 bytes read, 3 more expected)")
266 self.assertEqual(str(i),
267 "IncompleteRead(7 bytes read, 3 more expected)")
268 else:
269 self.fail('IncompleteRead expected')
270 finally:
271 resp.close()
272
Victor Stinner2c6aee92010-07-24 02:46:16 +0000273 def test_epipe(self):
274 sock = EPipeSocket(
275 "HTTP/1.0 401 Authorization Required\r\n"
276 "Content-type: text/html\r\n"
277 "WWW-Authenticate: Basic realm=\"example\"\r\n",
278 b"Content-Length")
279 conn = httplib.HTTPConnection("example.com")
280 conn.sock = sock
281 self.assertRaises(socket.error,
282 lambda: conn.request("PUT", "/url", "body"))
283 resp = conn.getresponse()
284 self.assertEqual(401, resp.status)
285 self.assertEqual("Basic realm=\"example\"",
286 resp.getheader("www-authenticate"))
287
Senthil Kumarand389cb52010-09-21 01:38:15 +0000288 def test_filenoattr(self):
289 # Just test the fileno attribute in the HTTPResponse Object.
290 body = "HTTP/1.1 200 Ok\r\n\r\nText"
291 sock = FakeSocket(body)
292 resp = httplib.HTTPResponse(sock)
293 self.assertTrue(hasattr(resp,'fileno'),
294 'HTTPResponse should expose a fileno attribute')
Georg Brandl23635032008-02-24 00:03:22 +0000295
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000296class OfflineTest(TestCase):
297 def test_responses(self):
298 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
299
Gregory P. Smith9d325212010-01-03 02:06:07 +0000300
301class SourceAddressTest(TestCase):
302 def setUp(self):
303 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
304 self.port = test_support.bind_port(self.serv)
305 self.source_port = test_support.find_unused_port()
306 self.serv.listen(5)
307 self.conn = None
308
309 def tearDown(self):
310 if self.conn:
311 self.conn.close()
312 self.conn = None
313 self.serv.close()
314 self.serv = None
315
316 def testHTTPConnectionSourceAddress(self):
317 self.conn = httplib.HTTPConnection(HOST, self.port,
318 source_address=('', self.source_port))
319 self.conn.connect()
320 self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
321
322 @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
323 'httplib.HTTPSConnection not defined')
324 def testHTTPSConnectionSourceAddress(self):
325 self.conn = httplib.HTTPSConnection(HOST, self.port,
326 source_address=('', self.source_port))
327 # We don't test anything here other the constructor not barfing as
328 # this code doesn't deal with setting up an active running SSL server
329 # for an ssl_wrapped connect() to actually return from.
330
331
Facundo Batista07c78be2007-03-23 18:54:07 +0000332class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000333 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000334
Facundo Batista07c78be2007-03-23 18:54:07 +0000335 def setUp(self):
336 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000337 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000338 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000339
340 def tearDown(self):
341 self.serv.close()
342 self.serv = None
343
344 def testTimeoutAttribute(self):
345 '''This will prove that the timeout gets through
346 HTTPConnection and into the socket.
347 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000348 # default -- use global socket timeout
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000349 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000350 socket.setdefaulttimeout(30)
351 try:
352 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
353 httpConn.connect()
354 finally:
355 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000356 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000357 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000358
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000359 # no timeout -- do not use global socket default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000360 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000361 socket.setdefaulttimeout(30)
362 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000363 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
364 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000365 httpConn.connect()
366 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000367 socket.setdefaulttimeout(None)
368 self.assertEqual(httpConn.sock.gettimeout(), None)
369 httpConn.close()
370
371 # a value
372 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
373 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000374 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000375 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000376
377
Facundo Batista70f996b2007-05-21 17:32:32 +0000378class HTTPSTimeoutTest(TestCase):
379# XXX Here should be tests for HTTPS, there isn't any right now!
380
381 def test_attributes(self):
382 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000383 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000384 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000385 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000386
Jeremy Hylton2c178252004-08-07 16:28:14 +0000387def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000388 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Gregory P. Smith9d325212010-01-03 02:06:07 +0000389 HTTPSTimeoutTest, SourceAddressTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000390
Georg Brandl71a20892006-10-29 20:24:01 +0000391if __name__ == '__main__':
392 test_main()