blob: cd54323f1ae26d93d22ecee0e19c53538bdd9005 [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
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 Pitrou72481782009-09-29 17:48:18 +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
Jeremy Hylton21d2e592008-11-29 00:09:16 +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
Jeremy Hylton21d2e592008-11-29 00:09:16 +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'
Jeremy Hylton21d2e592008-11-29 00:09:16 +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 Pitrou72481782009-09-29 17:48:18 +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 Peterson7d49bba2009-03-02 22:41:42 +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
Georg Brandl8c460d52008-02-24 00:14:24 +0000210 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000211 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
212 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000213 resp = httplib.HTTPResponse(sock, method="GET")
214 resp.begin()
215 self.assertEquals(resp.read(), 'Hello\r\n')
216 resp.close()
217
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000218 def test_incomplete_read(self):
219 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
220 resp = httplib.HTTPResponse(sock, method="GET")
221 resp.begin()
222 try:
223 resp.read()
224 except httplib.IncompleteRead as i:
225 self.assertEquals(i.partial, 'Hello\r\n')
226 self.assertEqual(repr(i),
227 "IncompleteRead(7 bytes read, 3 more expected)")
228 self.assertEqual(str(i),
229 "IncompleteRead(7 bytes read, 3 more expected)")
230 else:
231 self.fail('IncompleteRead expected')
232 finally:
233 resp.close()
234
Georg Brandl23635032008-02-24 00:03:22 +0000235
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000236class OfflineTest(TestCase):
237 def test_responses(self):
238 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
239
Facundo Batista07c78be2007-03-23 18:54:07 +0000240class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000241 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000242
Facundo Batista07c78be2007-03-23 18:54:07 +0000243 def setUp(self):
244 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000245 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000246 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000247
248 def tearDown(self):
249 self.serv.close()
250 self.serv = None
251
252 def testTimeoutAttribute(self):
253 '''This will prove that the timeout gets through
254 HTTPConnection and into the socket.
255 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000256 # default -- use global socket timeout
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000257 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000258 socket.setdefaulttimeout(30)
259 try:
260 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
261 httpConn.connect()
262 finally:
263 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000264 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000265 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000266
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000267 # no timeout -- do not use global socket default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000268 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000269 socket.setdefaulttimeout(30)
270 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000271 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
272 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000273 httpConn.connect()
274 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000275 socket.setdefaulttimeout(None)
276 self.assertEqual(httpConn.sock.gettimeout(), None)
277 httpConn.close()
278
279 # a value
280 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
281 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000282 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000283 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000284
285
Facundo Batista70f996b2007-05-21 17:32:32 +0000286class HTTPSTimeoutTest(TestCase):
287# XXX Here should be tests for HTTPS, there isn't any right now!
288
289 def test_attributes(self):
290 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000291 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000292 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000293 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000294
Jeremy Hylton2c178252004-08-07 16:28:14 +0000295def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000296 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
297 HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000298
Georg Brandl71a20892006-10-29 20:24:01 +0000299if __name__ == '__main__':
300 test_main()