blob: 72800e56ce2e5f2783f504c73edbb14488831e39 [file] [log] [blame]
Senthil Kumaranaa5f49e2010-10-03 18:26:07 +00001import httplib
Antoine Pitrou72481782009-09-29 17:48:18 +00002import array
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00003import httplib
4import StringIO
Facundo Batista07c78be2007-03-23 18:54:07 +00005import socket
Victor Stinner2c6aee92010-07-24 02:46:16 +00006import errno
Jeremy Hylton121d34a2003-07-08 12:36:58 +00007
Gregory P. Smith9d325212010-01-03 02:06:07 +00008import unittest
9TestCase = unittest.TestCase
Jeremy Hylton2c178252004-08-07 16:28:14 +000010
11from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000012
Trent Nelsone41b0062008-04-08 23:47:30 +000013HOST = test_support.HOST
14
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000015class FakeSocket:
Senthil Kumaran36f28f72014-05-16 18:51:46 -070016 def __init__(self, text, fileclass=StringIO.StringIO, host=None, port=None):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000017 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000018 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000019 self.data = ''
Senthil Kumaran36f28f72014-05-16 18:51:46 -070020 self.host = host
21 self.port = port
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000022
Jeremy Hylton2c178252004-08-07 16:28:14 +000023 def sendall(self, data):
Antoine Pitrou72481782009-09-29 17:48:18 +000024 self.data += ''.join(data)
Jeremy Hylton2c178252004-08-07 16:28:14 +000025
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000026 def makefile(self, mode, bufsize=None):
27 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000028 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000029 return self.fileclass(self.text)
30
Senthil Kumaran36f28f72014-05-16 18:51:46 -070031 def close(self):
32 pass
33
Victor Stinner2c6aee92010-07-24 02:46:16 +000034class EPipeSocket(FakeSocket):
35
36 def __init__(self, text, pipe_trigger):
37 # When sendall() is called with pipe_trigger, raise EPIPE.
38 FakeSocket.__init__(self, text)
39 self.pipe_trigger = pipe_trigger
40
41 def sendall(self, data):
42 if self.pipe_trigger in data:
43 raise socket.error(errno.EPIPE, "gotcha")
44 self.data += data
45
46 def close(self):
47 pass
48
Jeremy Hylton121d34a2003-07-08 12:36:58 +000049class NoEOFStringIO(StringIO.StringIO):
50 """Like StringIO, but raises AssertionError on EOF.
51
52 This is used below to test that httplib doesn't try to read
53 more from the underlying file than it should.
54 """
55 def read(self, n=-1):
56 data = StringIO.StringIO.read(self, n)
57 if data == '':
58 raise AssertionError('caller tried to read past EOF')
59 return data
60
61 def readline(self, length=None):
62 data = StringIO.StringIO.readline(self, length)
63 if data == '':
64 raise AssertionError('caller tried to read past EOF')
65 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000066
Jeremy Hylton2c178252004-08-07 16:28:14 +000067
68class HeaderTests(TestCase):
69 def test_auto_headers(self):
70 # Some headers are added automatically, but should not be added by
71 # .request() if they are explicitly set.
72
Jeremy Hylton2c178252004-08-07 16:28:14 +000073 class HeaderCountingBuffer(list):
74 def __init__(self):
75 self.count = {}
76 def append(self, item):
77 kv = item.split(':')
78 if len(kv) > 1:
79 # item is a 'Key: Value' header string
80 lcKey = kv[0].lower()
81 self.count.setdefault(lcKey, 0)
82 self.count[lcKey] += 1
83 list.append(self, item)
84
85 for explicit_header in True, False:
86 for header in 'Content-length', 'Host', 'Accept-encoding':
87 conn = httplib.HTTPConnection('example.com')
88 conn.sock = FakeSocket('blahblahblah')
89 conn._buffer = HeaderCountingBuffer()
90
91 body = 'spamspamspam'
92 headers = {}
93 if explicit_header:
94 headers[header] = str(len(body))
95 conn.request('POST', '/', body, headers)
96 self.assertEqual(conn._buffer.count[header.lower()], 1)
97
Senthil Kumaran618802d2012-05-19 16:52:21 +080098 def test_content_length_0(self):
99
100 class ContentLengthChecker(list):
101 def __init__(self):
102 list.__init__(self)
103 self.content_length = None
104 def append(self, item):
105 kv = item.split(':', 1)
106 if len(kv) > 1 and kv[0].lower() == 'content-length':
107 self.content_length = kv[1].strip()
108 list.append(self, item)
109
110 # POST with empty body
111 conn = httplib.HTTPConnection('example.com')
112 conn.sock = FakeSocket(None)
113 conn._buffer = ContentLengthChecker()
114 conn.request('POST', '/', '')
115 self.assertEqual(conn._buffer.content_length, '0',
116 'Header Content-Length not set')
117
118 # PUT request with empty body
119 conn = httplib.HTTPConnection('example.com')
120 conn.sock = FakeSocket(None)
121 conn._buffer = ContentLengthChecker()
122 conn.request('PUT', '/', '')
123 self.assertEqual(conn._buffer.content_length, '0',
124 'Header Content-Length not set')
125
Senthil Kumaranaa5f49e2010-10-03 18:26:07 +0000126 def test_putheader(self):
127 conn = httplib.HTTPConnection('example.com')
128 conn.sock = FakeSocket(None)
129 conn.putrequest('GET','/')
130 conn.putheader('Content-length',42)
Serhiy Storchaka528bed82014-02-08 14:49:55 +0200131 self.assertIn('Content-length: 42', conn._buffer)
Senthil Kumaranaa5f49e2010-10-03 18:26:07 +0000132
Senthil Kumaran501bfd82010-11-14 03:31:52 +0000133 def test_ipv6host_header(self):
134 # Default host header on IPv6 transaction should wrapped by [] if
135 # its actual IPv6 address
136 expected = 'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \
137 'Accept-Encoding: identity\r\n\r\n'
138 conn = httplib.HTTPConnection('[2001::]:81')
139 sock = FakeSocket('')
140 conn.sock = sock
141 conn.request('GET', '/foo')
142 self.assertTrue(sock.data.startswith(expected))
143
144 expected = 'GET /foo HTTP/1.1\r\nHost: [2001:102A::]\r\n' \
145 'Accept-Encoding: identity\r\n\r\n'
146 conn = httplib.HTTPConnection('[2001:102A::]')
147 sock = FakeSocket('')
148 conn.sock = sock
149 conn.request('GET', '/foo')
150 self.assertTrue(sock.data.startswith(expected))
151
152
Georg Brandl71a20892006-10-29 20:24:01 +0000153class BasicTest(TestCase):
154 def test_status_lines(self):
155 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +0000156
Georg Brandl71a20892006-10-29 20:24:01 +0000157 body = "HTTP/1.1 200 Ok\r\n\r\nText"
158 sock = FakeSocket(body)
159 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000160 resp.begin()
Serhiy Storchakac97f5ed2013-12-17 21:49:48 +0200161 self.assertEqual(resp.read(0), '') # Issue #20007
162 self.assertFalse(resp.isclosed())
Georg Brandl71a20892006-10-29 20:24:01 +0000163 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +0000164 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +0000165
Georg Brandl71a20892006-10-29 20:24:01 +0000166 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
167 sock = FakeSocket(body)
168 resp = httplib.HTTPResponse(sock)
169 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000170
Dirkjan Ochtmanebc73dc2010-02-24 04:49:00 +0000171 def test_bad_status_repr(self):
172 exc = httplib.BadStatusLine('')
Ezio Melotti2623a372010-11-21 13:34:58 +0000173 self.assertEqual(repr(exc), '''BadStatusLine("\'\'",)''')
Dirkjan Ochtmanebc73dc2010-02-24 04:49:00 +0000174
Facundo Batista70665902007-10-18 03:16:03 +0000175 def test_partial_reads(self):
Antoine Pitrou4113d2b2012-12-15 19:11:54 +0100176 # if we have a length, the system knows when to close itself
Facundo Batista70665902007-10-18 03:16:03 +0000177 # same behaviour than when we read the whole thing with read()
178 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
179 sock = FakeSocket(body)
180 resp = httplib.HTTPResponse(sock)
181 resp.begin()
182 self.assertEqual(resp.read(2), 'Te')
183 self.assertFalse(resp.isclosed())
184 self.assertEqual(resp.read(2), 'xt')
185 self.assertTrue(resp.isclosed())
186
Antoine Pitrou4113d2b2012-12-15 19:11:54 +0100187 def test_partial_reads_no_content_length(self):
188 # when no length is present, the socket should be gracefully closed when
189 # all data was read
190 body = "HTTP/1.1 200 Ok\r\n\r\nText"
191 sock = FakeSocket(body)
192 resp = httplib.HTTPResponse(sock)
193 resp.begin()
194 self.assertEqual(resp.read(2), 'Te')
195 self.assertFalse(resp.isclosed())
196 self.assertEqual(resp.read(2), 'xt')
197 self.assertEqual(resp.read(1), '')
198 self.assertTrue(resp.isclosed())
199
Antoine Pitroud66c0ee2013-02-02 22:49:34 +0100200 def test_partial_reads_incomplete_body(self):
201 # if the server shuts down the connection before the whole
202 # content-length is delivered, the socket is gracefully closed
203 body = "HTTP/1.1 200 Ok\r\nContent-Length: 10\r\n\r\nText"
204 sock = FakeSocket(body)
205 resp = httplib.HTTPResponse(sock)
206 resp.begin()
207 self.assertEqual(resp.read(2), 'Te')
208 self.assertFalse(resp.isclosed())
209 self.assertEqual(resp.read(2), 'xt')
210 self.assertEqual(resp.read(1), '')
211 self.assertTrue(resp.isclosed())
212
Georg Brandl71a20892006-10-29 20:24:01 +0000213 def test_host_port(self):
214 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000215
Łukasz Langa7a153902011-10-18 17:16:00 +0200216 # Note that httplib does not accept user:password@ in the host-port.
217 for hp in ("www.python.org:abc", "user:password@www.python.org"):
Georg Brandl71a20892006-10-29 20:24:01 +0000218 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
219
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000220 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
221 8000),
Georg Brandl71a20892006-10-29 20:24:01 +0000222 ("www.python.org:80", "www.python.org", 80),
223 ("www.python.org", "www.python.org", 80),
Łukasz Langa7a153902011-10-18 17:16:00 +0200224 ("www.python.org:", "www.python.org", 80),
Georg Brandl71a20892006-10-29 20:24:01 +0000225 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000226 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000227 c = http._conn
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000228 if h != c.host:
229 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
230 if p != c.port:
231 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000232
Georg Brandl71a20892006-10-29 20:24:01 +0000233 def test_response_headers(self):
234 # test response with multiple message headers with the same field name.
235 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000236 'Set-Cookie: Customer="WILE_E_COYOTE";'
237 ' Version="1"; Path="/acme"\r\n'
Georg Brandl71a20892006-10-29 20:24:01 +0000238 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
239 ' Path="/acme"\r\n'
240 '\r\n'
241 'No body\r\n')
242 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
243 ', '
244 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
245 s = FakeSocket(text)
246 r = httplib.HTTPResponse(s)
247 r.begin()
248 cookies = r.getheader("Set-Cookie")
249 if cookies != hdr:
250 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000251
Georg Brandl71a20892006-10-29 20:24:01 +0000252 def test_read_head(self):
253 # Test that the library doesn't attempt to read any data
254 # from a HEAD request. (Tickles SF bug #622042.)
255 sock = FakeSocket(
256 'HTTP/1.1 200 OK\r\n'
257 'Content-Length: 14432\r\n'
258 '\r\n',
259 NoEOFStringIO)
260 resp = httplib.HTTPResponse(sock, method="HEAD")
261 resp.begin()
262 if resp.read() != "":
263 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000264
Martin v. Löwis040a9272006-11-12 10:32:47 +0000265 def test_send_file(self):
266 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
267 'Accept-Encoding: identity\r\nContent-Length:'
268
269 body = open(__file__, 'rb')
270 conn = httplib.HTTPConnection('example.com')
271 sock = FakeSocket(body)
272 conn.sock = sock
273 conn.request('GET', '/foo', body)
274 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000275
Antoine Pitrou72481782009-09-29 17:48:18 +0000276 def test_send(self):
277 expected = 'this is a test this is only a test'
278 conn = httplib.HTTPConnection('example.com')
279 sock = FakeSocket(None)
280 conn.sock = sock
281 conn.send(expected)
Ezio Melotti2623a372010-11-21 13:34:58 +0000282 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000283 sock.data = ''
284 conn.send(array.array('c', expected))
Ezio Melotti2623a372010-11-21 13:34:58 +0000285 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000286 sock.data = ''
287 conn.send(StringIO.StringIO(expected))
Ezio Melotti2623a372010-11-21 13:34:58 +0000288 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000289
Georg Brandl23635032008-02-24 00:03:22 +0000290 def test_chunked(self):
291 chunked_start = (
292 'HTTP/1.1 200 OK\r\n'
293 'Transfer-Encoding: chunked\r\n\r\n'
294 'a\r\n'
295 'hello worl\r\n'
296 '1\r\n'
297 'd\r\n'
298 )
299 sock = FakeSocket(chunked_start + '0\r\n')
300 resp = httplib.HTTPResponse(sock, method="GET")
301 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000302 self.assertEqual(resp.read(), 'hello world')
Georg Brandl23635032008-02-24 00:03:22 +0000303 resp.close()
304
305 for x in ('', 'foo\r\n'):
306 sock = FakeSocket(chunked_start + x)
307 resp = httplib.HTTPResponse(sock, method="GET")
308 resp.begin()
309 try:
310 resp.read()
311 except httplib.IncompleteRead, i:
Ezio Melotti2623a372010-11-21 13:34:58 +0000312 self.assertEqual(i.partial, 'hello world')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000313 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
314 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000315 else:
316 self.fail('IncompleteRead expected')
317 finally:
318 resp.close()
319
Senthil Kumaraned9204342010-04-28 17:20:43 +0000320 def test_chunked_head(self):
321 chunked_start = (
322 'HTTP/1.1 200 OK\r\n'
323 'Transfer-Encoding: chunked\r\n\r\n'
324 'a\r\n'
325 'hello world\r\n'
326 '1\r\n'
327 'd\r\n'
328 )
329 sock = FakeSocket(chunked_start + '0\r\n')
330 resp = httplib.HTTPResponse(sock, method="HEAD")
331 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000332 self.assertEqual(resp.read(), '')
333 self.assertEqual(resp.status, 200)
334 self.assertEqual(resp.reason, 'OK')
Senthil Kumaranfb695012010-06-04 17:17:09 +0000335 self.assertTrue(resp.isclosed())
Senthil Kumaraned9204342010-04-28 17:20:43 +0000336
Georg Brandl8c460d52008-02-24 00:14:24 +0000337 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000338 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
339 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000340 resp = httplib.HTTPResponse(sock, method="GET")
341 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000342 self.assertEqual(resp.read(), 'Hello\r\n')
Antoine Pitroud66c0ee2013-02-02 22:49:34 +0100343 self.assertTrue(resp.isclosed())
Georg Brandl8c460d52008-02-24 00:14:24 +0000344
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000345 def test_incomplete_read(self):
346 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
347 resp = httplib.HTTPResponse(sock, method="GET")
348 resp.begin()
349 try:
350 resp.read()
351 except httplib.IncompleteRead as i:
Ezio Melotti2623a372010-11-21 13:34:58 +0000352 self.assertEqual(i.partial, 'Hello\r\n')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000353 self.assertEqual(repr(i),
354 "IncompleteRead(7 bytes read, 3 more expected)")
355 self.assertEqual(str(i),
356 "IncompleteRead(7 bytes read, 3 more expected)")
Antoine Pitroud66c0ee2013-02-02 22:49:34 +0100357 self.assertTrue(resp.isclosed())
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000358 else:
359 self.fail('IncompleteRead expected')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000360
Victor Stinner2c6aee92010-07-24 02:46:16 +0000361 def test_epipe(self):
362 sock = EPipeSocket(
363 "HTTP/1.0 401 Authorization Required\r\n"
364 "Content-type: text/html\r\n"
365 "WWW-Authenticate: Basic realm=\"example\"\r\n",
366 b"Content-Length")
367 conn = httplib.HTTPConnection("example.com")
368 conn.sock = sock
369 self.assertRaises(socket.error,
370 lambda: conn.request("PUT", "/url", "body"))
371 resp = conn.getresponse()
372 self.assertEqual(401, resp.status)
373 self.assertEqual("Basic realm=\"example\"",
374 resp.getheader("www-authenticate"))
375
Senthil Kumarand389cb52010-09-21 01:38:15 +0000376 def test_filenoattr(self):
377 # Just test the fileno attribute in the HTTPResponse Object.
378 body = "HTTP/1.1 200 Ok\r\n\r\nText"
379 sock = FakeSocket(body)
380 resp = httplib.HTTPResponse(sock)
381 self.assertTrue(hasattr(resp,'fileno'),
382 'HTTPResponse should expose a fileno attribute')
Georg Brandl23635032008-02-24 00:03:22 +0000383
Antoine Pitroud7b6ac62010-12-18 18:18:21 +0000384 # Test lines overflowing the max line size (_MAXLINE in http.client)
385
386 def test_overflowing_status_line(self):
387 self.skipTest("disabled for HTTP 0.9 support")
388 body = "HTTP/1.1 200 Ok" + "k" * 65536 + "\r\n"
389 resp = httplib.HTTPResponse(FakeSocket(body))
390 self.assertRaises((httplib.LineTooLong, httplib.BadStatusLine), resp.begin)
391
392 def test_overflowing_header_line(self):
393 body = (
394 'HTTP/1.1 200 OK\r\n'
395 'X-Foo: bar' + 'r' * 65536 + '\r\n\r\n'
396 )
397 resp = httplib.HTTPResponse(FakeSocket(body))
398 self.assertRaises(httplib.LineTooLong, resp.begin)
399
400 def test_overflowing_chunked_line(self):
401 body = (
402 'HTTP/1.1 200 OK\r\n'
403 'Transfer-Encoding: chunked\r\n\r\n'
404 + '0' * 65536 + 'a\r\n'
405 'hello world\r\n'
406 '0\r\n'
407 )
408 resp = httplib.HTTPResponse(FakeSocket(body))
409 resp.begin()
410 self.assertRaises(httplib.LineTooLong, resp.read)
411
Senthil Kumaranf5aaf6f2012-04-29 10:15:31 +0800412 def test_early_eof(self):
413 # Test httpresponse with no \r\n termination,
414 body = "HTTP/1.1 200 Ok"
415 sock = FakeSocket(body)
416 resp = httplib.HTTPResponse(sock)
417 resp.begin()
418 self.assertEqual(resp.read(), '')
419 self.assertTrue(resp.isclosed())
Antoine Pitroud7b6ac62010-12-18 18:18:21 +0000420
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000421class OfflineTest(TestCase):
422 def test_responses(self):
Ezio Melotti2623a372010-11-21 13:34:58 +0000423 self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found")
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000424
Gregory P. Smith9d325212010-01-03 02:06:07 +0000425
426class SourceAddressTest(TestCase):
427 def setUp(self):
428 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
429 self.port = test_support.bind_port(self.serv)
430 self.source_port = test_support.find_unused_port()
431 self.serv.listen(5)
432 self.conn = None
433
434 def tearDown(self):
435 if self.conn:
436 self.conn.close()
437 self.conn = None
438 self.serv.close()
439 self.serv = None
440
441 def testHTTPConnectionSourceAddress(self):
442 self.conn = httplib.HTTPConnection(HOST, self.port,
443 source_address=('', self.source_port))
444 self.conn.connect()
445 self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
446
447 @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
448 'httplib.HTTPSConnection not defined')
449 def testHTTPSConnectionSourceAddress(self):
450 self.conn = httplib.HTTPSConnection(HOST, self.port,
451 source_address=('', self.source_port))
452 # We don't test anything here other the constructor not barfing as
453 # this code doesn't deal with setting up an active running SSL server
454 # for an ssl_wrapped connect() to actually return from.
455
456
Facundo Batista07c78be2007-03-23 18:54:07 +0000457class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000458 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000459
Facundo Batista07c78be2007-03-23 18:54:07 +0000460 def setUp(self):
461 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000462 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000463 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000464
465 def tearDown(self):
466 self.serv.close()
467 self.serv = None
468
469 def testTimeoutAttribute(self):
470 '''This will prove that the timeout gets through
471 HTTPConnection and into the socket.
472 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000473 # default -- use global socket timeout
Serhiy Storchaka528bed82014-02-08 14:49:55 +0200474 self.assertIsNone(socket.getdefaulttimeout())
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000475 socket.setdefaulttimeout(30)
476 try:
477 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
478 httpConn.connect()
479 finally:
480 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000481 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000482 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000483
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000484 # no timeout -- do not use global socket default
Serhiy Storchaka528bed82014-02-08 14:49:55 +0200485 self.assertIsNone(socket.getdefaulttimeout())
Facundo Batista14553b02007-03-23 20:23:08 +0000486 socket.setdefaulttimeout(30)
487 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000488 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
489 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000490 httpConn.connect()
491 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000492 socket.setdefaulttimeout(None)
493 self.assertEqual(httpConn.sock.gettimeout(), None)
494 httpConn.close()
495
496 # a value
497 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
498 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000499 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000500 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000501
502
Facundo Batista70f996b2007-05-21 17:32:32 +0000503class HTTPSTimeoutTest(TestCase):
504# XXX Here should be tests for HTTPS, there isn't any right now!
505
506 def test_attributes(self):
507 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000508 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000509 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000510 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000511
Petri Lehtinen6d089df2011-10-26 21:25:56 +0300512 @unittest.skipIf(not hasattr(httplib, 'HTTPS'), 'httplib.HTTPS not available')
Łukasz Langa7a153902011-10-18 17:16:00 +0200513 def test_host_port(self):
514 # Check invalid host_port
515
516 # Note that httplib does not accept user:password@ in the host-port.
517 for hp in ("www.python.org:abc", "user:password@www.python.org"):
518 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
519
520 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
521 8000),
522 ("pypi.python.org:443", "pypi.python.org", 443),
523 ("pypi.python.org", "pypi.python.org", 443),
524 ("pypi.python.org:", "pypi.python.org", 443),
525 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443)):
526 http = httplib.HTTPS(hp)
527 c = http._conn
528 if h != c.host:
529 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
530 if p != c.port:
531 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
532
533
Senthil Kumaran36f28f72014-05-16 18:51:46 -0700534class TunnelTests(TestCase):
535 def test_connect(self):
536 response_text = (
537 'HTTP/1.0 200 OK\r\n\r\n' # Reply to CONNECT
538 'HTTP/1.1 200 OK\r\n' # Reply to HEAD
539 'Content-Length: 42\r\n\r\n'
540 )
541
542 def create_connection(address, timeout=None, source_address=None):
543 return FakeSocket(response_text, host=address[0], port=address[1])
544
545 conn = httplib.HTTPConnection('proxy.com')
546 conn._create_connection = create_connection
547
548 # Once connected, we should not be able to tunnel anymore
549 conn.connect()
550 self.assertRaises(RuntimeError, conn.set_tunnel, 'destination.com')
551
552 # But if close the connection, we are good.
553 conn.close()
554 conn.set_tunnel('destination.com')
555 conn.request('HEAD', '/', '')
556
557 self.assertEqual(conn.sock.host, 'proxy.com')
558 self.assertEqual(conn.sock.port, 80)
559 self.assertTrue('CONNECT destination.com' in conn.sock.data)
560 self.assertTrue('Host: destination.com' in conn.sock.data)
561
562 self.assertTrue('Host: proxy.com' not in conn.sock.data)
563
564 conn.close()
565
566 conn.request('PUT', '/', '')
567 self.assertEqual(conn.sock.host, 'proxy.com')
568 self.assertEqual(conn.sock.port, 80)
569 self.assertTrue('CONNECT destination.com' in conn.sock.data)
570 self.assertTrue('Host: destination.com' in conn.sock.data)
571
572
Jeremy Hylton2c178252004-08-07 16:28:14 +0000573def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000574 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Senthil Kumaran36f28f72014-05-16 18:51:46 -0700575 HTTPSTimeoutTest, SourceAddressTest, TunnelTests)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000576
Georg Brandl71a20892006-10-29 20:24:01 +0000577if __name__ == '__main__':
578 test_main()