blob: 4b2a638a49a1692a03517178bbafa1ec1991b91f [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
Berker Peksagb7414e02014-08-05 07:15:57 +0300265 def test_too_many_headers(self):
266 headers = '\r\n'.join('Header%d: foo' % i for i in xrange(200)) + '\r\n'
267 text = ('HTTP/1.1 200 OK\r\n' + headers)
268 s = FakeSocket(text)
269 r = httplib.HTTPResponse(s)
270 self.assertRaises(httplib.HTTPException, r.begin)
271
Martin v. Löwis040a9272006-11-12 10:32:47 +0000272 def test_send_file(self):
273 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
274 'Accept-Encoding: identity\r\nContent-Length:'
275
276 body = open(__file__, 'rb')
277 conn = httplib.HTTPConnection('example.com')
278 sock = FakeSocket(body)
279 conn.sock = sock
280 conn.request('GET', '/foo', body)
281 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000282
Antoine Pitrou72481782009-09-29 17:48:18 +0000283 def test_send(self):
284 expected = 'this is a test this is only a test'
285 conn = httplib.HTTPConnection('example.com')
286 sock = FakeSocket(None)
287 conn.sock = sock
288 conn.send(expected)
Ezio Melotti2623a372010-11-21 13:34:58 +0000289 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000290 sock.data = ''
291 conn.send(array.array('c', expected))
Ezio Melotti2623a372010-11-21 13:34:58 +0000292 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000293 sock.data = ''
294 conn.send(StringIO.StringIO(expected))
Ezio Melotti2623a372010-11-21 13:34:58 +0000295 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000296
Georg Brandl23635032008-02-24 00:03:22 +0000297 def test_chunked(self):
298 chunked_start = (
299 'HTTP/1.1 200 OK\r\n'
300 'Transfer-Encoding: chunked\r\n\r\n'
301 'a\r\n'
302 'hello worl\r\n'
303 '1\r\n'
304 'd\r\n'
305 )
306 sock = FakeSocket(chunked_start + '0\r\n')
307 resp = httplib.HTTPResponse(sock, method="GET")
308 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000309 self.assertEqual(resp.read(), 'hello world')
Georg Brandl23635032008-02-24 00:03:22 +0000310 resp.close()
311
312 for x in ('', 'foo\r\n'):
313 sock = FakeSocket(chunked_start + x)
314 resp = httplib.HTTPResponse(sock, method="GET")
315 resp.begin()
316 try:
317 resp.read()
318 except httplib.IncompleteRead, i:
Ezio Melotti2623a372010-11-21 13:34:58 +0000319 self.assertEqual(i.partial, 'hello world')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000320 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
321 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000322 else:
323 self.fail('IncompleteRead expected')
324 finally:
325 resp.close()
326
Senthil Kumaraned9204342010-04-28 17:20:43 +0000327 def test_chunked_head(self):
328 chunked_start = (
329 'HTTP/1.1 200 OK\r\n'
330 'Transfer-Encoding: chunked\r\n\r\n'
331 'a\r\n'
332 'hello world\r\n'
333 '1\r\n'
334 'd\r\n'
335 )
336 sock = FakeSocket(chunked_start + '0\r\n')
337 resp = httplib.HTTPResponse(sock, method="HEAD")
338 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000339 self.assertEqual(resp.read(), '')
340 self.assertEqual(resp.status, 200)
341 self.assertEqual(resp.reason, 'OK')
Senthil Kumaranfb695012010-06-04 17:17:09 +0000342 self.assertTrue(resp.isclosed())
Senthil Kumaraned9204342010-04-28 17:20:43 +0000343
Georg Brandl8c460d52008-02-24 00:14:24 +0000344 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000345 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
346 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000347 resp = httplib.HTTPResponse(sock, method="GET")
348 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000349 self.assertEqual(resp.read(), 'Hello\r\n')
Antoine Pitroud66c0ee2013-02-02 22:49:34 +0100350 self.assertTrue(resp.isclosed())
Georg Brandl8c460d52008-02-24 00:14:24 +0000351
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000352 def test_incomplete_read(self):
353 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
354 resp = httplib.HTTPResponse(sock, method="GET")
355 resp.begin()
356 try:
357 resp.read()
358 except httplib.IncompleteRead as i:
Ezio Melotti2623a372010-11-21 13:34:58 +0000359 self.assertEqual(i.partial, 'Hello\r\n')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000360 self.assertEqual(repr(i),
361 "IncompleteRead(7 bytes read, 3 more expected)")
362 self.assertEqual(str(i),
363 "IncompleteRead(7 bytes read, 3 more expected)")
Antoine Pitroud66c0ee2013-02-02 22:49:34 +0100364 self.assertTrue(resp.isclosed())
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000365 else:
366 self.fail('IncompleteRead expected')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000367
Victor Stinner2c6aee92010-07-24 02:46:16 +0000368 def test_epipe(self):
369 sock = EPipeSocket(
370 "HTTP/1.0 401 Authorization Required\r\n"
371 "Content-type: text/html\r\n"
372 "WWW-Authenticate: Basic realm=\"example\"\r\n",
373 b"Content-Length")
374 conn = httplib.HTTPConnection("example.com")
375 conn.sock = sock
376 self.assertRaises(socket.error,
377 lambda: conn.request("PUT", "/url", "body"))
378 resp = conn.getresponse()
379 self.assertEqual(401, resp.status)
380 self.assertEqual("Basic realm=\"example\"",
381 resp.getheader("www-authenticate"))
382
Senthil Kumarand389cb52010-09-21 01:38:15 +0000383 def test_filenoattr(self):
384 # Just test the fileno attribute in the HTTPResponse Object.
385 body = "HTTP/1.1 200 Ok\r\n\r\nText"
386 sock = FakeSocket(body)
387 resp = httplib.HTTPResponse(sock)
388 self.assertTrue(hasattr(resp,'fileno'),
389 'HTTPResponse should expose a fileno attribute')
Georg Brandl23635032008-02-24 00:03:22 +0000390
Antoine Pitroud7b6ac62010-12-18 18:18:21 +0000391 # Test lines overflowing the max line size (_MAXLINE in http.client)
392
393 def test_overflowing_status_line(self):
394 self.skipTest("disabled for HTTP 0.9 support")
395 body = "HTTP/1.1 200 Ok" + "k" * 65536 + "\r\n"
396 resp = httplib.HTTPResponse(FakeSocket(body))
397 self.assertRaises((httplib.LineTooLong, httplib.BadStatusLine), resp.begin)
398
399 def test_overflowing_header_line(self):
400 body = (
401 'HTTP/1.1 200 OK\r\n'
402 'X-Foo: bar' + 'r' * 65536 + '\r\n\r\n'
403 )
404 resp = httplib.HTTPResponse(FakeSocket(body))
405 self.assertRaises(httplib.LineTooLong, resp.begin)
406
407 def test_overflowing_chunked_line(self):
408 body = (
409 'HTTP/1.1 200 OK\r\n'
410 'Transfer-Encoding: chunked\r\n\r\n'
411 + '0' * 65536 + 'a\r\n'
412 'hello world\r\n'
413 '0\r\n'
414 )
415 resp = httplib.HTTPResponse(FakeSocket(body))
416 resp.begin()
417 self.assertRaises(httplib.LineTooLong, resp.read)
418
Senthil Kumaranf5aaf6f2012-04-29 10:15:31 +0800419 def test_early_eof(self):
420 # Test httpresponse with no \r\n termination,
421 body = "HTTP/1.1 200 Ok"
422 sock = FakeSocket(body)
423 resp = httplib.HTTPResponse(sock)
424 resp.begin()
425 self.assertEqual(resp.read(), '')
426 self.assertTrue(resp.isclosed())
Antoine Pitroud7b6ac62010-12-18 18:18:21 +0000427
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000428class OfflineTest(TestCase):
429 def test_responses(self):
Ezio Melotti2623a372010-11-21 13:34:58 +0000430 self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found")
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000431
Gregory P. Smith9d325212010-01-03 02:06:07 +0000432
433class SourceAddressTest(TestCase):
434 def setUp(self):
435 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
436 self.port = test_support.bind_port(self.serv)
437 self.source_port = test_support.find_unused_port()
438 self.serv.listen(5)
439 self.conn = None
440
441 def tearDown(self):
442 if self.conn:
443 self.conn.close()
444 self.conn = None
445 self.serv.close()
446 self.serv = None
447
448 def testHTTPConnectionSourceAddress(self):
449 self.conn = httplib.HTTPConnection(HOST, self.port,
450 source_address=('', self.source_port))
451 self.conn.connect()
452 self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
453
454 @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
455 'httplib.HTTPSConnection not defined')
456 def testHTTPSConnectionSourceAddress(self):
457 self.conn = httplib.HTTPSConnection(HOST, self.port,
458 source_address=('', self.source_port))
459 # We don't test anything here other the constructor not barfing as
460 # this code doesn't deal with setting up an active running SSL server
461 # for an ssl_wrapped connect() to actually return from.
462
463
Facundo Batista07c78be2007-03-23 18:54:07 +0000464class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000465 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000466
Facundo Batista07c78be2007-03-23 18:54:07 +0000467 def setUp(self):
468 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000469 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000470 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000471
472 def tearDown(self):
473 self.serv.close()
474 self.serv = None
475
476 def testTimeoutAttribute(self):
477 '''This will prove that the timeout gets through
478 HTTPConnection and into the socket.
479 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000480 # default -- use global socket timeout
Serhiy Storchaka528bed82014-02-08 14:49:55 +0200481 self.assertIsNone(socket.getdefaulttimeout())
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000482 socket.setdefaulttimeout(30)
483 try:
484 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
485 httpConn.connect()
486 finally:
487 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000488 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000489 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000490
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000491 # no timeout -- do not use global socket default
Serhiy Storchaka528bed82014-02-08 14:49:55 +0200492 self.assertIsNone(socket.getdefaulttimeout())
Facundo Batista14553b02007-03-23 20:23:08 +0000493 socket.setdefaulttimeout(30)
494 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000495 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
496 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000497 httpConn.connect()
498 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000499 socket.setdefaulttimeout(None)
500 self.assertEqual(httpConn.sock.gettimeout(), None)
501 httpConn.close()
502
503 # a value
504 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
505 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000506 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000507 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000508
509
Facundo Batista70f996b2007-05-21 17:32:32 +0000510class HTTPSTimeoutTest(TestCase):
511# XXX Here should be tests for HTTPS, there isn't any right now!
512
513 def test_attributes(self):
514 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000515 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000516 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000517 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000518
Petri Lehtinen6d089df2011-10-26 21:25:56 +0300519 @unittest.skipIf(not hasattr(httplib, 'HTTPS'), 'httplib.HTTPS not available')
Łukasz Langa7a153902011-10-18 17:16:00 +0200520 def test_host_port(self):
521 # Check invalid host_port
522
523 # Note that httplib does not accept user:password@ in the host-port.
524 for hp in ("www.python.org:abc", "user:password@www.python.org"):
525 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
526
527 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
528 8000),
529 ("pypi.python.org:443", "pypi.python.org", 443),
530 ("pypi.python.org", "pypi.python.org", 443),
531 ("pypi.python.org:", "pypi.python.org", 443),
532 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443)):
533 http = httplib.HTTPS(hp)
534 c = http._conn
535 if h != c.host:
536 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
537 if p != c.port:
538 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
539
540
Senthil Kumaran36f28f72014-05-16 18:51:46 -0700541class TunnelTests(TestCase):
542 def test_connect(self):
543 response_text = (
544 'HTTP/1.0 200 OK\r\n\r\n' # Reply to CONNECT
545 'HTTP/1.1 200 OK\r\n' # Reply to HEAD
546 'Content-Length: 42\r\n\r\n'
547 )
548
549 def create_connection(address, timeout=None, source_address=None):
550 return FakeSocket(response_text, host=address[0], port=address[1])
551
552 conn = httplib.HTTPConnection('proxy.com')
553 conn._create_connection = create_connection
554
555 # Once connected, we should not be able to tunnel anymore
556 conn.connect()
557 self.assertRaises(RuntimeError, conn.set_tunnel, 'destination.com')
558
559 # But if close the connection, we are good.
560 conn.close()
561 conn.set_tunnel('destination.com')
562 conn.request('HEAD', '/', '')
563
564 self.assertEqual(conn.sock.host, 'proxy.com')
565 self.assertEqual(conn.sock.port, 80)
566 self.assertTrue('CONNECT destination.com' in conn.sock.data)
567 self.assertTrue('Host: destination.com' in conn.sock.data)
568
569 self.assertTrue('Host: proxy.com' not in conn.sock.data)
570
571 conn.close()
572
573 conn.request('PUT', '/', '')
574 self.assertEqual(conn.sock.host, 'proxy.com')
575 self.assertEqual(conn.sock.port, 80)
576 self.assertTrue('CONNECT destination.com' in conn.sock.data)
577 self.assertTrue('Host: destination.com' in conn.sock.data)
578
579
Jeremy Hylton2c178252004-08-07 16:28:14 +0000580def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000581 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Senthil Kumaran36f28f72014-05-16 18:51:46 -0700582 HTTPSTimeoutTest, SourceAddressTest, TunnelTests)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000583
Georg Brandl71a20892006-10-29 20:24:01 +0000584if __name__ == '__main__':
585 test_main()