Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(37926)

Delta Between Two Patch Sets: Lib/test/test_httplib.py

Issue 16037: httplib: header parsing is not delimited
Left Patch Set: Created 6 years ago
Right Patch Set: Created 5 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/httplib.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 import httplib
1 import array 2 import array
2 import httplib 3 import httplib
3 import StringIO 4 import StringIO
4 import socket 5 import socket
5 6 import errno
6 from unittest import TestCase 7
8 import unittest
9 TestCase = unittest.TestCase
7 10
8 from test import test_support 11 from test import test_support
9 12
10 HOST = test_support.HOST 13 HOST = test_support.HOST
11 14
12 class FakeSocket: 15 class FakeSocket:
13 def __init__(self, text, fileclass=StringIO.StringIO): 16 def __init__(self, text, fileclass=StringIO.StringIO, host=None, port=None):
14 self.text = text 17 self.text = text
15 self.fileclass = fileclass 18 self.fileclass = fileclass
16 self.data = '' 19 self.data = ''
20 self.host = host
21 self.port = port
17 22
18 def sendall(self, data): 23 def sendall(self, data):
19 self.data += ''.join(data) 24 self.data += ''.join(data)
20 25
21 def makefile(self, mode, bufsize=None): 26 def makefile(self, mode, bufsize=None):
22 if mode != 'r' and mode != 'rb': 27 if mode != 'r' and mode != 'rb':
23 raise httplib.UnimplementedFileMode() 28 raise httplib.UnimplementedFileMode()
24 return self.fileclass(self.text) 29 return self.fileclass(self.text)
30
31 def close(self):
32 pass
33
34 class 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
25 48
26 class NoEOFStringIO(StringIO.StringIO): 49 class NoEOFStringIO(StringIO.StringIO):
27 """Like StringIO, but raises AssertionError on EOF. 50 """Like StringIO, but raises AssertionError on EOF.
28 51
29 This is used below to test that httplib doesn't try to read 52 This is used below to test that httplib doesn't try to read
30 more from the underlying file than it should. 53 more from the underlying file than it should.
31 """ 54 """
32 def read(self, n=-1): 55 def read(self, n=-1):
33 data = StringIO.StringIO.read(self, n) 56 data = StringIO.StringIO.read(self, n)
34 if data == '': 57 if data == '':
35 raise AssertionError('caller tried to read past EOF') 58 raise AssertionError('caller tried to read past EOF')
36 return data 59 return data
37 60
38 def readline(self, length=None): 61 def readline(self, length=None):
39 data = StringIO.StringIO.readline(self, length) 62 data = StringIO.StringIO.readline(self, length)
40 if data == '': 63 if data == '':
41 raise AssertionError('caller tried to read past EOF') 64 raise AssertionError('caller tried to read past EOF')
42 return data 65 return data
43 66
44 67
45 class HeaderTests(TestCase): 68 class HeaderTests(TestCase):
46 def test_auto_headers(self): 69 def test_auto_headers(self):
47 # Some headers are added automatically, but should not be added by 70 # Some headers are added automatically, but should not be added by
48 # .request() if they are explicitly set. 71 # .request() if they are explicitly set.
49
50 import httplib
51 72
52 class HeaderCountingBuffer(list): 73 class HeaderCountingBuffer(list):
53 def __init__(self): 74 def __init__(self):
54 self.count = {} 75 self.count = {}
55 def append(self, item): 76 def append(self, item):
56 kv = item.split(':') 77 kv = item.split(':')
57 if len(kv) > 1: 78 if len(kv) > 1:
58 # item is a 'Key: Value' header string 79 # item is a 'Key: Value' header string
59 lcKey = kv[0].lower() 80 lcKey = kv[0].lower()
60 self.count.setdefault(lcKey, 0) 81 self.count.setdefault(lcKey, 0)
61 self.count[lcKey] += 1 82 self.count[lcKey] += 1
62 list.append(self, item) 83 list.append(self, item)
63 84
64 for explicit_header in True, False: 85 for explicit_header in True, False:
65 for header in 'Content-length', 'Host', 'Accept-encoding': 86 for header in 'Content-length', 'Host', 'Accept-encoding':
66 conn = httplib.HTTPConnection('example.com') 87 conn = httplib.HTTPConnection('example.com')
67 conn.sock = FakeSocket('blahblahblah') 88 conn.sock = FakeSocket('blahblahblah')
68 conn._buffer = HeaderCountingBuffer() 89 conn._buffer = HeaderCountingBuffer()
69 90
70 body = 'spamspamspam' 91 body = 'spamspamspam'
71 headers = {} 92 headers = {}
72 if explicit_header: 93 if explicit_header:
73 headers[header] = str(len(body)) 94 headers[header] = str(len(body))
74 conn.request('POST', '/', body, headers) 95 conn.request('POST', '/', body, headers)
75 self.assertEqual(conn._buffer.count[header.lower()], 1) 96 self.assertEqual(conn._buffer.count[header.lower()], 1)
76 97
98 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
126 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)
131 self.assertIn('Content-length: 42', conn._buffer)
132
133 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
77 class BasicTest(TestCase): 153 class BasicTest(TestCase):
78 def test_status_lines(self): 154 def test_status_lines(self):
79 # Test HTTP status lines 155 # Test HTTP status lines
80 156
81 body = "HTTP/1.1 200 Ok\r\n\r\nText" 157 body = "HTTP/1.1 200 Ok\r\n\r\nText"
82 sock = FakeSocket(body) 158 sock = FakeSocket(body)
83 resp = httplib.HTTPResponse(sock) 159 resp = httplib.HTTPResponse(sock)
84 resp.begin() 160 resp.begin()
161 self.assertEqual(resp.read(0), '') # Issue #20007
162 self.assertFalse(resp.isclosed())
85 self.assertEqual(resp.read(), 'Text') 163 self.assertEqual(resp.read(), 'Text')
86 self.assertTrue(resp.isclosed()) 164 self.assertTrue(resp.isclosed())
87 165
88 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText" 166 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
89 sock = FakeSocket(body) 167 sock = FakeSocket(body)
90 resp = httplib.HTTPResponse(sock) 168 resp = httplib.HTTPResponse(sock)
91 self.assertRaises(httplib.BadStatusLine, resp.begin) 169 self.assertRaises(httplib.BadStatusLine, resp.begin)
92 170
171 def test_bad_status_repr(self):
172 exc = httplib.BadStatusLine('')
173 self.assertEqual(repr(exc), '''BadStatusLine("\'\'",)''')
174
93 def test_partial_reads(self): 175 def test_partial_reads(self):
94 # if we have a lenght, the system knows when to close itself 176 # if we have a length, the system knows when to close itself
95 # same behaviour than when we read the whole thing with read() 177 # 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" 178 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
97 sock = FakeSocket(body) 179 sock = FakeSocket(body)
98 resp = httplib.HTTPResponse(sock) 180 resp = httplib.HTTPResponse(sock)
99 resp.begin() 181 resp.begin()
100 self.assertEqual(resp.read(2), 'Te') 182 self.assertEqual(resp.read(2), 'Te')
101 self.assertFalse(resp.isclosed()) 183 self.assertFalse(resp.isclosed())
102 self.assertEqual(resp.read(2), 'xt') 184 self.assertEqual(resp.read(2), 'xt')
103 self.assertTrue(resp.isclosed()) 185 self.assertTrue(resp.isclosed())
104 186
187 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
200 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
105 def test_host_port(self): 213 def test_host_port(self):
106 # Check invalid host_port 214 # Check invalid host_port
107 215
108 for hp in ("www.python.org:abc", "www.python.org:"): 216 # 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"):
109 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp) 218 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
110 219
111 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 220 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
112 8000), 221 8000),
113 ("www.python.org:80", "www.python.org", 80), 222 ("www.python.org:80", "www.python.org", 80),
114 ("www.python.org", "www.python.org", 80), 223 ("www.python.org", "www.python.org", 80),
224 ("www.python.org:", "www.python.org", 80),
115 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)): 225 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
116 http = httplib.HTTP(hp) 226 http = httplib.HTTP(hp)
117 c = http._conn 227 c = http._conn
118 if h != c.host: 228 if h != c.host:
119 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host)) 229 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
120 if p != c.port: 230 if p != c.port:
121 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host)) 231 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
122 232
123 def test_response_headers(self): 233 def test_response_headers(self):
124 # test response with multiple message headers with the same field name. 234 # test response with multiple message headers with the same field name.
(...skipping 25 matching lines...) Expand all
150 resp = httplib.HTTPResponse(sock, method="HEAD") 260 resp = httplib.HTTPResponse(sock, method="HEAD")
151 resp.begin() 261 resp.begin()
152 if resp.read() != "": 262 if resp.read() != "":
153 self.fail("Did not expect response from HEAD request") 263 self.fail("Did not expect response from HEAD request")
154 264
155 def test_too_many_headers(self): 265 def test_too_many_headers(self):
156 headers = '\r\n'.join('Header%d: foo' % i for i in xrange(200)) + '\r\n' 266 headers = '\r\n'.join('Header%d: foo' % i for i in xrange(200)) + '\r\n'
157 text = ('HTTP/1.1 200 OK\r\n' + headers) 267 text = ('HTTP/1.1 200 OK\r\n' + headers)
158 s = FakeSocket(text) 268 s = FakeSocket(text)
159 r = httplib.HTTPResponse(s) 269 r = httplib.HTTPResponse(s)
160 self.assertRaises(httplib.TooManyHeaders, r.begin) 270 self.assertRaises(httplib.HTTPException, r.begin)
161 271
162 def test_send_file(self): 272 def test_send_file(self):
163 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \ 273 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
164 'Accept-Encoding: identity\r\nContent-Length:' 274 'Accept-Encoding: identity\r\nContent-Length:'
165 275
166 body = open(__file__, 'rb') 276 body = open(__file__, 'rb')
167 conn = httplib.HTTPConnection('example.com') 277 conn = httplib.HTTPConnection('example.com')
168 sock = FakeSocket(body) 278 sock = FakeSocket(body)
169 conn.sock = sock 279 conn.sock = sock
170 conn.request('GET', '/foo', body) 280 conn.request('GET', '/foo', body)
171 self.assertTrue(sock.data.startswith(expected)) 281 self.assertTrue(sock.data.startswith(expected))
172 282
173 def test_send(self): 283 def test_send(self):
174 expected = 'this is a test this is only a test' 284 expected = 'this is a test this is only a test'
175 conn = httplib.HTTPConnection('example.com') 285 conn = httplib.HTTPConnection('example.com')
176 sock = FakeSocket(None) 286 sock = FakeSocket(None)
177 conn.sock = sock 287 conn.sock = sock
178 conn.send(expected) 288 conn.send(expected)
179 self.assertEquals(expected, sock.data) 289 self.assertEqual(expected, sock.data)
180 sock.data = '' 290 sock.data = ''
181 conn.send(array.array('c', expected)) 291 conn.send(array.array('c', expected))
182 self.assertEquals(expected, sock.data) 292 self.assertEqual(expected, sock.data)
183 sock.data = '' 293 sock.data = ''
184 conn.send(StringIO.StringIO(expected)) 294 conn.send(StringIO.StringIO(expected))
185 self.assertEquals(expected, sock.data) 295 self.assertEqual(expected, sock.data)
186 296
187 def test_chunked(self): 297 def test_chunked(self):
188 chunked_start = ( 298 chunked_start = (
189 'HTTP/1.1 200 OK\r\n' 299 'HTTP/1.1 200 OK\r\n'
190 'Transfer-Encoding: chunked\r\n\r\n' 300 'Transfer-Encoding: chunked\r\n\r\n'
191 'a\r\n' 301 'a\r\n'
192 'hello worl\r\n' 302 'hello worl\r\n'
193 '1\r\n' 303 '1\r\n'
194 'd\r\n' 304 'd\r\n'
195 ) 305 )
196 sock = FakeSocket(chunked_start + '0\r\n') 306 sock = FakeSocket(chunked_start + '0\r\n')
197 resp = httplib.HTTPResponse(sock, method="GET") 307 resp = httplib.HTTPResponse(sock, method="GET")
198 resp.begin() 308 resp.begin()
199 self.assertEquals(resp.read(), 'hello world') 309 self.assertEqual(resp.read(), 'hello world')
200 resp.close() 310 resp.close()
201 311
202 for x in ('', 'foo\r\n'): 312 for x in ('', 'foo\r\n'):
203 sock = FakeSocket(chunked_start + x) 313 sock = FakeSocket(chunked_start + x)
204 resp = httplib.HTTPResponse(sock, method="GET") 314 resp = httplib.HTTPResponse(sock, method="GET")
205 resp.begin() 315 resp.begin()
206 try: 316 try:
207 resp.read() 317 resp.read()
208 except httplib.IncompleteRead, i: 318 except httplib.IncompleteRead, i:
209 self.assertEquals(i.partial, 'hello world') 319 self.assertEqual(i.partial, 'hello world')
210 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)') 320 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
211 self.assertEqual(str(i),'IncompleteRead(11 bytes read)') 321 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
212 else: 322 else:
213 self.fail('IncompleteRead expected') 323 self.fail('IncompleteRead expected')
214 finally: 324 finally:
215 resp.close() 325 resp.close()
216 326
217 def test_chunked_head(self): 327 def test_chunked_head(self):
218 chunked_start = ( 328 chunked_start = (
219 'HTTP/1.1 200 OK\r\n' 329 'HTTP/1.1 200 OK\r\n'
220 'Transfer-Encoding: chunked\r\n\r\n' 330 'Transfer-Encoding: chunked\r\n\r\n'
221 'a\r\n' 331 'a\r\n'
222 'hello world\r\n' 332 'hello world\r\n'
223 '1\r\n' 333 '1\r\n'
224 'd\r\n' 334 'd\r\n'
225 ) 335 )
226 sock = FakeSocket(chunked_start + '0\r\n') 336 sock = FakeSocket(chunked_start + '0\r\n')
227 resp = httplib.HTTPResponse(sock, method="HEAD") 337 resp = httplib.HTTPResponse(sock, method="HEAD")
228 resp.begin() 338 resp.begin()
229 self.assertEquals(resp.read(), '') 339 self.assertEqual(resp.read(), '')
230 self.assertEquals(resp.status, 200) 340 self.assertEqual(resp.status, 200)
231 self.assertEquals(resp.reason, 'OK') 341 self.assertEqual(resp.reason, 'OK')
232 self.assertTrue(resp.isclosed()) 342 self.assertTrue(resp.isclosed())
233 343
234 def test_negative_content_length(self): 344 def test_negative_content_length(self):
235 sock = FakeSocket('HTTP/1.1 200 OK\r\n' 345 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
236 'Content-Length: -1\r\n\r\nHello\r\n') 346 'Content-Length: -1\r\n\r\nHello\r\n')
237 resp = httplib.HTTPResponse(sock, method="GET") 347 resp = httplib.HTTPResponse(sock, method="GET")
238 resp.begin() 348 resp.begin()
239 self.assertEquals(resp.read(), 'Hello\r\n') 349 self.assertEqual(resp.read(), 'Hello\r\n')
240 resp.close() 350 self.assertTrue(resp.isclosed())
241 351
242 def test_incomplete_read(self): 352 def test_incomplete_read(self):
243 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\ n') 353 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\ n')
244 resp = httplib.HTTPResponse(sock, method="GET") 354 resp = httplib.HTTPResponse(sock, method="GET")
245 resp.begin() 355 resp.begin()
246 try: 356 try:
247 resp.read() 357 resp.read()
248 except httplib.IncompleteRead as i: 358 except httplib.IncompleteRead as i:
249 self.assertEquals(i.partial, 'Hello\r\n') 359 self.assertEqual(i.partial, 'Hello\r\n')
250 self.assertEqual(repr(i), 360 self.assertEqual(repr(i),
251 "IncompleteRead(7 bytes read, 3 more expected)") 361 "IncompleteRead(7 bytes read, 3 more expected)")
252 self.assertEqual(str(i), 362 self.assertEqual(str(i),
253 "IncompleteRead(7 bytes read, 3 more expected)") 363 "IncompleteRead(7 bytes read, 3 more expected)")
364 self.assertTrue(resp.isclosed())
254 else: 365 else:
255 self.fail('IncompleteRead expected') 366 self.fail('IncompleteRead expected')
256 finally: 367
257 resp.close() 368 def test_epipe(self):
258 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
383 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')
390
391 # 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.beg in)
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
419 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())
259 427
260 class OfflineTest(TestCase): 428 class OfflineTest(TestCase):
261 def test_responses(self): 429 def test_responses(self):
262 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found") 430 self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found")
431
432
433 class 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
263 463
264 class TimeoutTest(TestCase): 464 class TimeoutTest(TestCase):
265 PORT = None 465 PORT = None
266 466
267 def setUp(self): 467 def setUp(self):
268 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 468 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
269 TimeoutTest.PORT = test_support.bind_port(self.serv) 469 TimeoutTest.PORT = test_support.bind_port(self.serv)
270 self.serv.listen(5) 470 self.serv.listen(5)
271 471
272 def tearDown(self): 472 def tearDown(self):
273 self.serv.close() 473 self.serv.close()
274 self.serv = None 474 self.serv = None
275 475
276 def testTimeoutAttribute(self): 476 def testTimeoutAttribute(self):
277 '''This will prove that the timeout gets through 477 '''This will prove that the timeout gets through
278 HTTPConnection and into the socket. 478 HTTPConnection and into the socket.
279 ''' 479 '''
280 # default -- use global socket timeout 480 # default -- use global socket timeout
281 self.assert_(socket.getdefaulttimeout() is None) 481 self.assertIsNone(socket.getdefaulttimeout())
282 socket.setdefaulttimeout(30) 482 socket.setdefaulttimeout(30)
283 try: 483 try:
284 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT) 484 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
285 httpConn.connect() 485 httpConn.connect()
286 finally: 486 finally:
287 socket.setdefaulttimeout(None) 487 socket.setdefaulttimeout(None)
288 self.assertEqual(httpConn.sock.gettimeout(), 30) 488 self.assertEqual(httpConn.sock.gettimeout(), 30)
289 httpConn.close() 489 httpConn.close()
290 490
291 # no timeout -- do not use global socket default 491 # no timeout -- do not use global socket default
292 self.assert_(socket.getdefaulttimeout() is None) 492 self.assertIsNone(socket.getdefaulttimeout())
293 socket.setdefaulttimeout(30) 493 socket.setdefaulttimeout(30)
294 try: 494 try:
295 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, 495 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
296 timeout=None) 496 timeout=None)
297 httpConn.connect() 497 httpConn.connect()
298 finally: 498 finally:
299 socket.setdefaulttimeout(None) 499 socket.setdefaulttimeout(None)
300 self.assertEqual(httpConn.sock.gettimeout(), None) 500 self.assertEqual(httpConn.sock.gettimeout(), None)
301 httpConn.close() 501 httpConn.close()
302 502
303 # a value 503 # a value
304 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30) 504 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
305 httpConn.connect() 505 httpConn.connect()
306 self.assertEqual(httpConn.sock.gettimeout(), 30) 506 self.assertEqual(httpConn.sock.gettimeout(), 30)
307 httpConn.close() 507 httpConn.close()
308 508
309 509
310 class HTTPSTimeoutTest(TestCase): 510 class HTTPSTimeoutTest(TestCase):
311 # XXX Here should be tests for HTTPS, there isn't any right now! 511 # XXX Here should be tests for HTTPS, there isn't any right now!
312 512
313 def test_attributes(self): 513 def test_attributes(self):
314 # simple test to check it's storing it 514 # simple test to check it's storing it
315 if hasattr(httplib, 'HTTPSConnection'): 515 if hasattr(httplib, 'HTTPSConnection'):
316 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) 516 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
317 self.assertEqual(h.timeout, 30) 517 self.assertEqual(h.timeout, 30)
318 518
519 @unittest.skipIf(not hasattr(httplib, 'HTTPS'), 'httplib.HTTPS not available ')
520 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
541 class 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
319 def test_main(verbose=None): 580 def test_main(verbose=None):
320 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, 581 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
321 HTTPSTimeoutTest) 582 HTTPSTimeoutTest, SourceAddressTest, TunnelTests)
322 583
323 if __name__ == '__main__': 584 if __name__ == '__main__':
324 test_main() 585 test_main()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+