blob: 107b904ebc9106f8043adc5d90ea634b642ab3f6 [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
Georg Brandl8c460d52008-02-24 00:14:24 +0000215 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000216 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
217 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000218 resp = httplib.HTTPResponse(sock, method="GET")
219 resp.begin()
220 self.assertEquals(resp.read(), 'Hello\r\n')
221 resp.close()
222
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000223 def test_incomplete_read(self):
224 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
225 resp = httplib.HTTPResponse(sock, method="GET")
226 resp.begin()
227 try:
228 resp.read()
229 except httplib.IncompleteRead as i:
230 self.assertEquals(i.partial, 'Hello\r\n')
231 self.assertEqual(repr(i),
232 "IncompleteRead(7 bytes read, 3 more expected)")
233 self.assertEqual(str(i),
234 "IncompleteRead(7 bytes read, 3 more expected)")
235 else:
236 self.fail('IncompleteRead expected')
237 finally:
238 resp.close()
239
Georg Brandl23635032008-02-24 00:03:22 +0000240
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000241class OfflineTest(TestCase):
242 def test_responses(self):
243 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
244
Gregory P. Smith9d325212010-01-03 02:06:07 +0000245
246class SourceAddressTest(TestCase):
247 def setUp(self):
248 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
249 self.port = test_support.bind_port(self.serv)
250 self.source_port = test_support.find_unused_port()
251 self.serv.listen(5)
252 self.conn = None
253
254 def tearDown(self):
255 if self.conn:
256 self.conn.close()
257 self.conn = None
258 self.serv.close()
259 self.serv = None
260
261 def testHTTPConnectionSourceAddress(self):
262 self.conn = httplib.HTTPConnection(HOST, self.port,
263 source_address=('', self.source_port))
264 self.conn.connect()
265 self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
266
267 @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
268 'httplib.HTTPSConnection not defined')
269 def testHTTPSConnectionSourceAddress(self):
270 self.conn = httplib.HTTPSConnection(HOST, self.port,
271 source_address=('', self.source_port))
272 # We don't test anything here other the constructor not barfing as
273 # this code doesn't deal with setting up an active running SSL server
274 # for an ssl_wrapped connect() to actually return from.
275
276
Facundo Batista07c78be2007-03-23 18:54:07 +0000277class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000278 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000279
Facundo Batista07c78be2007-03-23 18:54:07 +0000280 def setUp(self):
281 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000282 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000283 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000284
285 def tearDown(self):
286 self.serv.close()
287 self.serv = None
288
289 def testTimeoutAttribute(self):
290 '''This will prove that the timeout gets through
291 HTTPConnection and into the socket.
292 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000293 # default -- use global socket timeout
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000294 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000295 socket.setdefaulttimeout(30)
296 try:
297 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
298 httpConn.connect()
299 finally:
300 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000301 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000302 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000303
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000304 # no timeout -- do not use global socket default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000305 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000306 socket.setdefaulttimeout(30)
307 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000308 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
309 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000310 httpConn.connect()
311 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000312 socket.setdefaulttimeout(None)
313 self.assertEqual(httpConn.sock.gettimeout(), None)
314 httpConn.close()
315
316 # a value
317 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
318 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000319 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000320 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000321
322
Facundo Batista70f996b2007-05-21 17:32:32 +0000323class HTTPSTimeoutTest(TestCase):
324# XXX Here should be tests for HTTPS, there isn't any right now!
325
326 def test_attributes(self):
327 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000328 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000329 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000330 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000331
Jeremy Hylton2c178252004-08-07 16:28:14 +0000332def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000333 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Gregory P. Smith9d325212010-01-03 02:06:07 +0000334 HTTPSTimeoutTest, SourceAddressTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000335
Georg Brandl71a20892006-10-29 20:24:01 +0000336if __name__ == '__main__':
337 test_main()