blob: 730e8852a1d0b883481cdf7b870f39f54d4e2dc6 [file] [log] [blame]
Antoine Pitrou530e1ac2009-09-29 18:14:09 +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
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
Trent Nelsone41b0062008-04-08 23:47:30 +000010HOST = test_support.HOST
11
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000012class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000013 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000014 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000015 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000016 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000017
Jeremy Hylton2c178252004-08-07 16:28:14 +000018 def sendall(self, data):
Antoine Pitrou530e1ac2009-09-29 18:14:09 +000019 self.data += ''.join(data)
Jeremy Hylton2c178252004-08-07 16:28:14 +000020
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000021 def makefile(self, mode, bufsize=None):
22 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000023 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000024 return self.fileclass(self.text)
25
26class NoEOFStringIO(StringIO.StringIO):
27 """Like StringIO, but raises AssertionError on EOF.
28
29 This is used below to test that httplib doesn't try to read
30 more from the underlying file than it should.
31 """
32 def read(self, n=-1):
33 data = StringIO.StringIO.read(self, n)
34 if data == '':
35 raise AssertionError('caller tried to read past EOF')
36 return data
37
38 def readline(self, length=None):
39 data = StringIO.StringIO.readline(self, length)
40 if data == '':
41 raise AssertionError('caller tried to read past EOF')
42 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000043
Jeremy Hylton2c178252004-08-07 16:28:14 +000044
45class HeaderTests(TestCase):
46 def test_auto_headers(self):
47 # Some headers are added automatically, but should not be added by
48 # .request() if they are explicitly set.
49
50 import httplib
51
52 class HeaderCountingBuffer(list):
53 def __init__(self):
54 self.count = {}
55 def append(self, item):
56 kv = item.split(':')
57 if len(kv) > 1:
58 # item is a 'Key: Value' header string
59 lcKey = kv[0].lower()
60 self.count.setdefault(lcKey, 0)
61 self.count[lcKey] += 1
62 list.append(self, item)
63
64 for explicit_header in True, False:
65 for header in 'Content-length', 'Host', 'Accept-encoding':
66 conn = httplib.HTTPConnection('example.com')
67 conn.sock = FakeSocket('blahblahblah')
68 conn._buffer = HeaderCountingBuffer()
69
70 body = 'spamspamspam'
71 headers = {}
72 if explicit_header:
73 headers[header] = str(len(body))
74 conn.request('POST', '/', body, headers)
75 self.assertEqual(conn._buffer.count[header.lower()], 1)
76
Georg Brandl71a20892006-10-29 20:24:01 +000077class BasicTest(TestCase):
78 def test_status_lines(self):
79 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000080
Georg Brandl71a20892006-10-29 20:24:01 +000081 body = "HTTP/1.1 200 Ok\r\n\r\nText"
82 sock = FakeSocket(body)
83 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000084 resp.begin()
Georg Brandl71a20892006-10-29 20:24:01 +000085 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +000086 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000087
Georg Brandl71a20892006-10-29 20:24:01 +000088 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
89 sock = FakeSocket(body)
90 resp = httplib.HTTPResponse(sock)
91 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000092
Facundo Batista70665902007-10-18 03:16:03 +000093 def test_partial_reads(self):
94 # if we have a lenght, the system knows when to close itself
95 # same behaviour than when we read the whole thing with read()
96 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
97 sock = FakeSocket(body)
98 resp = httplib.HTTPResponse(sock)
99 resp.begin()
100 self.assertEqual(resp.read(2), 'Te')
101 self.assertFalse(resp.isclosed())
102 self.assertEqual(resp.read(2), 'xt')
103 self.assertTrue(resp.isclosed())
104
Georg Brandl71a20892006-10-29 20:24:01 +0000105 def test_host_port(self):
106 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000107
Georg Brandl71a20892006-10-29 20:24:01 +0000108 for hp in ("www.python.org:abc", "www.python.org:"):
109 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
110
Georg Brandl5c7f8fb2008-12-05 09:00:55 +0000111 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
112 8000),
Georg Brandl71a20892006-10-29 20:24:01 +0000113 ("www.python.org:80", "www.python.org", 80),
114 ("www.python.org", "www.python.org", 80),
115 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000116 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000117 c = http._conn
Georg Brandl5c7f8fb2008-12-05 09:00:55 +0000118 if h != c.host:
119 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
120 if p != c.port:
121 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000122
Georg Brandl71a20892006-10-29 20:24:01 +0000123 def test_response_headers(self):
124 # test response with multiple message headers with the same field name.
125 text = ('HTTP/1.1 200 OK\r\n'
Georg Brandl5c7f8fb2008-12-05 09:00:55 +0000126 'Set-Cookie: Customer="WILE_E_COYOTE";'
127 ' Version="1"; Path="/acme"\r\n'
Georg Brandl71a20892006-10-29 20:24:01 +0000128 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
129 ' Path="/acme"\r\n'
130 '\r\n'
131 'No body\r\n')
132 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
133 ', '
134 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
135 s = FakeSocket(text)
136 r = httplib.HTTPResponse(s)
137 r.begin()
138 cookies = r.getheader("Set-Cookie")
139 if cookies != hdr:
140 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000141
Georg Brandl71a20892006-10-29 20:24:01 +0000142 def test_read_head(self):
143 # Test that the library doesn't attempt to read any data
144 # from a HEAD request. (Tickles SF bug #622042.)
145 sock = FakeSocket(
146 'HTTP/1.1 200 OK\r\n'
147 'Content-Length: 14432\r\n'
148 '\r\n',
149 NoEOFStringIO)
150 resp = httplib.HTTPResponse(sock, method="HEAD")
151 resp.begin()
152 if resp.read() != "":
153 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000154
Martin v. Löwis040a9272006-11-12 10:32:47 +0000155 def test_send_file(self):
156 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
157 'Accept-Encoding: identity\r\nContent-Length:'
158
159 body = open(__file__, 'rb')
160 conn = httplib.HTTPConnection('example.com')
161 sock = FakeSocket(body)
162 conn.sock = sock
163 conn.request('GET', '/foo', body)
164 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000165
Antoine Pitrou530e1ac2009-09-29 18:14:09 +0000166 def test_send(self):
167 expected = 'this is a test this is only a test'
168 conn = httplib.HTTPConnection('example.com')
169 sock = FakeSocket(None)
170 conn.sock = sock
171 conn.send(expected)
172 self.assertEquals(expected, sock.data)
173 sock.data = ''
174 conn.send(array.array('c', expected))
175 self.assertEquals(expected, sock.data)
176 sock.data = ''
177 conn.send(StringIO.StringIO(expected))
178 self.assertEquals(expected, sock.data)
179
Georg Brandl23635032008-02-24 00:03:22 +0000180 def test_chunked(self):
181 chunked_start = (
182 'HTTP/1.1 200 OK\r\n'
183 'Transfer-Encoding: chunked\r\n\r\n'
184 'a\r\n'
185 'hello worl\r\n'
186 '1\r\n'
187 'd\r\n'
188 )
189 sock = FakeSocket(chunked_start + '0\r\n')
190 resp = httplib.HTTPResponse(sock, method="GET")
191 resp.begin()
192 self.assertEquals(resp.read(), 'hello world')
193 resp.close()
194
195 for x in ('', 'foo\r\n'):
196 sock = FakeSocket(chunked_start + x)
197 resp = httplib.HTTPResponse(sock, method="GET")
198 resp.begin()
199 try:
200 resp.read()
201 except httplib.IncompleteRead, i:
202 self.assertEquals(i.partial, 'hello world')
Benjamin Petersona97bed92009-03-02 22:46:11 +0000203 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
204 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000205 else:
206 self.fail('IncompleteRead expected')
207 finally:
208 resp.close()
209
Senthil Kumaran379eaac2010-04-28 17:25:58 +0000210 def test_chunked_head(self):
211 chunked_start = (
212 'HTTP/1.1 200 OK\r\n'
213 'Transfer-Encoding: chunked\r\n\r\n'
214 'a\r\n'
215 'hello world\r\n'
216 '1\r\n'
217 'd\r\n'
218 )
219 sock = FakeSocket(chunked_start + '0\r\n')
220 resp = httplib.HTTPResponse(sock, method="HEAD")
221 resp.begin()
222 self.assertEquals(resp.read(), '')
223 self.assertEquals(resp.status, 200)
224 self.assertEquals(resp.reason, 'OK')
Senthil Kumaran3bde59c2010-06-04 17:20:13 +0000225 self.assertTrue(resp.isclosed())
Senthil Kumaran379eaac2010-04-28 17:25:58 +0000226
Georg Brandl8c460d52008-02-24 00:14:24 +0000227 def test_negative_content_length(self):
Georg Brandl5c7f8fb2008-12-05 09:00:55 +0000228 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
229 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000230 resp = httplib.HTTPResponse(sock, method="GET")
231 resp.begin()
232 self.assertEquals(resp.read(), 'Hello\r\n')
233 resp.close()
234
Benjamin Petersona97bed92009-03-02 22:46:11 +0000235 def test_incomplete_read(self):
236 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
237 resp = httplib.HTTPResponse(sock, method="GET")
238 resp.begin()
239 try:
240 resp.read()
241 except httplib.IncompleteRead as i:
242 self.assertEquals(i.partial, 'Hello\r\n')
243 self.assertEqual(repr(i),
244 "IncompleteRead(7 bytes read, 3 more expected)")
245 self.assertEqual(str(i),
246 "IncompleteRead(7 bytes read, 3 more expected)")
247 else:
248 self.fail('IncompleteRead expected')
249 finally:
250 resp.close()
251
Georg Brandl23635032008-02-24 00:03:22 +0000252
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000253class OfflineTest(TestCase):
254 def test_responses(self):
255 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
256
Facundo Batista07c78be2007-03-23 18:54:07 +0000257class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000258 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000259
Facundo Batista07c78be2007-03-23 18:54:07 +0000260 def setUp(self):
261 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000262 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000263 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000264
265 def tearDown(self):
266 self.serv.close()
267 self.serv = None
268
269 def testTimeoutAttribute(self):
270 '''This will prove that the timeout gets through
271 HTTPConnection and into the socket.
272 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000273 # default -- use global socket timeout
274 self.assert_(socket.getdefaulttimeout() is None)
275 socket.setdefaulttimeout(30)
276 try:
277 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
278 httpConn.connect()
279 finally:
280 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000281 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000282 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000283
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000284 # no timeout -- do not use global socket default
285 self.assert_(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000286 socket.setdefaulttimeout(30)
287 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000288 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
289 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000290 httpConn.connect()
291 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000292 socket.setdefaulttimeout(None)
293 self.assertEqual(httpConn.sock.gettimeout(), None)
294 httpConn.close()
295
296 # a value
297 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
298 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000299 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000300 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000301
302
Facundo Batista70f996b2007-05-21 17:32:32 +0000303class HTTPSTimeoutTest(TestCase):
304# XXX Here should be tests for HTTPS, there isn't any right now!
305
306 def test_attributes(self):
307 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000308 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000309 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000310 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000311
Jeremy Hylton2c178252004-08-07 16:28:14 +0000312def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000313 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
314 HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000315
Georg Brandl71a20892006-10-29 20:24:01 +0000316if __name__ == '__main__':
317 test_main()