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

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

Issue 16037: httplib: header parsing is not delimited
Left Patch Set: Created 5 years, 9 months ago
Right Patch Set: Created 4 years, 10 months 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 httplib
2 import array 2 import array
3 import httplib 3 import httplib
4 import StringIO 4 import StringIO
5 import socket 5 import socket
6 import errno 6 import errno
7 7
8 import unittest 8 import unittest
9 TestCase = unittest.TestCase 9 TestCase = unittest.TestCase
10 10
11 from test import test_support 11 from test import test_support
12 12
13 HOST = test_support.HOST 13 HOST = test_support.HOST
14 14
15 class FakeSocket: 15 class FakeSocket:
16 def __init__(self, text, fileclass=StringIO.StringIO): 16 def __init__(self, text, fileclass=StringIO.StringIO, host=None, port=None):
17 self.text = text 17 self.text = text
18 self.fileclass = fileclass 18 self.fileclass = fileclass
19 self.data = '' 19 self.data = ''
20 self.host = host
21 self.port = port
20 22
21 def sendall(self, data): 23 def sendall(self, data):
22 self.data += ''.join(data) 24 self.data += ''.join(data)
23 25
24 def makefile(self, mode, bufsize=None): 26 def makefile(self, mode, bufsize=None):
25 if mode != 'r' and mode != 'rb': 27 if mode != 'r' and mode != 'rb':
26 raise httplib.UnimplementedFileMode() 28 raise httplib.UnimplementedFileMode()
27 return self.fileclass(self.text) 29 return self.fileclass(self.text)
30
31 def close(self):
32 pass
28 33
29 class EPipeSocket(FakeSocket): 34 class EPipeSocket(FakeSocket):
30 35
31 def __init__(self, text, pipe_trigger): 36 def __init__(self, text, pipe_trigger):
32 # When sendall() is called with pipe_trigger, raise EPIPE. 37 # When sendall() is called with pipe_trigger, raise EPIPE.
33 FakeSocket.__init__(self, text) 38 FakeSocket.__init__(self, text)
34 self.pipe_trigger = pipe_trigger 39 self.pipe_trigger = pipe_trigger
35 40
36 def sendall(self, data): 41 def sendall(self, data):
37 if self.pipe_trigger in data: 42 if self.pipe_trigger in data:
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 conn._buffer = ContentLengthChecker() 121 conn._buffer = ContentLengthChecker()
117 conn.request('PUT', '/', '') 122 conn.request('PUT', '/', '')
118 self.assertEqual(conn._buffer.content_length, '0', 123 self.assertEqual(conn._buffer.content_length, '0',
119 'Header Content-Length not set') 124 'Header Content-Length not set')
120 125
121 def test_putheader(self): 126 def test_putheader(self):
122 conn = httplib.HTTPConnection('example.com') 127 conn = httplib.HTTPConnection('example.com')
123 conn.sock = FakeSocket(None) 128 conn.sock = FakeSocket(None)
124 conn.putrequest('GET','/') 129 conn.putrequest('GET','/')
125 conn.putheader('Content-length',42) 130 conn.putheader('Content-length',42)
126 self.assertTrue('Content-length: 42' in conn._buffer) 131 self.assertIn('Content-length: 42', conn._buffer)
127 132
128 def test_ipv6host_header(self): 133 def test_ipv6host_header(self):
129 # Default host header on IPv6 transaction should wrapped by [] if 134 # Default host header on IPv6 transaction should wrapped by [] if
130 # its actual IPv6 address 135 # its actual IPv6 address
131 expected = 'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \ 136 expected = 'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \
132 'Accept-Encoding: identity\r\n\r\n' 137 'Accept-Encoding: identity\r\n\r\n'
133 conn = httplib.HTTPConnection('[2001::]:81') 138 conn = httplib.HTTPConnection('[2001::]:81')
134 sock = FakeSocket('') 139 sock = FakeSocket('')
135 conn.sock = sock 140 conn.sock = sock
136 conn.request('GET', '/foo') 141 conn.request('GET', '/foo')
137 self.assertTrue(sock.data.startswith(expected)) 142 self.assertTrue(sock.data.startswith(expected))
138 143
139 expected = 'GET /foo HTTP/1.1\r\nHost: [2001:102A::]\r\n' \ 144 expected = 'GET /foo HTTP/1.1\r\nHost: [2001:102A::]\r\n' \
140 'Accept-Encoding: identity\r\n\r\n' 145 'Accept-Encoding: identity\r\n\r\n'
141 conn = httplib.HTTPConnection('[2001:102A::]') 146 conn = httplib.HTTPConnection('[2001:102A::]')
142 sock = FakeSocket('') 147 sock = FakeSocket('')
143 conn.sock = sock 148 conn.sock = sock
144 conn.request('GET', '/foo') 149 conn.request('GET', '/foo')
145 self.assertTrue(sock.data.startswith(expected)) 150 self.assertTrue(sock.data.startswith(expected))
146 151
147 152
148 class BasicTest(TestCase): 153 class BasicTest(TestCase):
149 def test_status_lines(self): 154 def test_status_lines(self):
150 # Test HTTP status lines 155 # Test HTTP status lines
151 156
152 body = "HTTP/1.1 200 Ok\r\n\r\nText" 157 body = "HTTP/1.1 200 Ok\r\n\r\nText"
153 sock = FakeSocket(body) 158 sock = FakeSocket(body)
154 resp = httplib.HTTPResponse(sock) 159 resp = httplib.HTTPResponse(sock)
155 resp.begin() 160 resp.begin()
161 self.assertEqual(resp.read(0), '') # Issue #20007
162 self.assertFalse(resp.isclosed())
156 self.assertEqual(resp.read(), 'Text') 163 self.assertEqual(resp.read(), 'Text')
157 self.assertTrue(resp.isclosed()) 164 self.assertTrue(resp.isclosed())
158 165
159 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"
160 sock = FakeSocket(body) 167 sock = FakeSocket(body)
161 resp = httplib.HTTPResponse(sock) 168 resp = httplib.HTTPResponse(sock)
162 self.assertRaises(httplib.BadStatusLine, resp.begin) 169 self.assertRaises(httplib.BadStatusLine, resp.begin)
163 170
164 def test_bad_status_repr(self): 171 def test_bad_status_repr(self):
165 exc = httplib.BadStatusLine('') 172 exc = httplib.BadStatusLine('')
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 resp = httplib.HTTPResponse(sock, method="HEAD") 260 resp = httplib.HTTPResponse(sock, method="HEAD")
254 resp.begin() 261 resp.begin()
255 if resp.read() != "": 262 if resp.read() != "":
256 self.fail("Did not expect response from HEAD request") 263 self.fail("Did not expect response from HEAD request")
257 264
258 def test_too_many_headers(self): 265 def test_too_many_headers(self):
259 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'
260 text = ('HTTP/1.1 200 OK\r\n' + headers) 267 text = ('HTTP/1.1 200 OK\r\n' + headers)
261 s = FakeSocket(text) 268 s = FakeSocket(text)
262 r = httplib.HTTPResponse(s) 269 r = httplib.HTTPResponse(s)
263 self.assertRaises(httplib.TooManyHeaders, r.begin) 270 self.assertRaises(httplib.HTTPException, r.begin)
264 271
265 def test_send_file(self): 272 def test_send_file(self):
266 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' \
267 'Accept-Encoding: identity\r\nContent-Length:' 274 'Accept-Encoding: identity\r\nContent-Length:'
268 275
269 body = open(__file__, 'rb') 276 body = open(__file__, 'rb')
270 conn = httplib.HTTPConnection('example.com') 277 conn = httplib.HTTPConnection('example.com')
271 sock = FakeSocket(body) 278 sock = FakeSocket(body)
272 conn.sock = sock 279 conn.sock = sock
273 conn.request('GET', '/foo', body) 280 conn.request('GET', '/foo', body)
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 471
465 def tearDown(self): 472 def tearDown(self):
466 self.serv.close() 473 self.serv.close()
467 self.serv = None 474 self.serv = None
468 475
469 def testTimeoutAttribute(self): 476 def testTimeoutAttribute(self):
470 '''This will prove that the timeout gets through 477 '''This will prove that the timeout gets through
471 HTTPConnection and into the socket. 478 HTTPConnection and into the socket.
472 ''' 479 '''
473 # default -- use global socket timeout 480 # default -- use global socket timeout
474 self.assertTrue(socket.getdefaulttimeout() is None) 481 self.assertIsNone(socket.getdefaulttimeout())
475 socket.setdefaulttimeout(30) 482 socket.setdefaulttimeout(30)
476 try: 483 try:
477 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT) 484 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
478 httpConn.connect() 485 httpConn.connect()
479 finally: 486 finally:
480 socket.setdefaulttimeout(None) 487 socket.setdefaulttimeout(None)
481 self.assertEqual(httpConn.sock.gettimeout(), 30) 488 self.assertEqual(httpConn.sock.gettimeout(), 30)
482 httpConn.close() 489 httpConn.close()
483 490
484 # no timeout -- do not use global socket default 491 # no timeout -- do not use global socket default
485 self.assertTrue(socket.getdefaulttimeout() is None) 492 self.assertIsNone(socket.getdefaulttimeout())
486 socket.setdefaulttimeout(30) 493 socket.setdefaulttimeout(30)
487 try: 494 try:
488 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, 495 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
489 timeout=None) 496 timeout=None)
490 httpConn.connect() 497 httpConn.connect()
491 finally: 498 finally:
492 socket.setdefaulttimeout(None) 499 socket.setdefaulttimeout(None)
493 self.assertEqual(httpConn.sock.gettimeout(), None) 500 self.assertEqual(httpConn.sock.gettimeout(), None)
494 httpConn.close() 501 httpConn.close()
495 502
(...skipping 28 matching lines...) Expand all
524 ("pypi.python.org:", "pypi.python.org", 443), 531 ("pypi.python.org:", "pypi.python.org", 443),
525 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443)): 532 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443)):
526 http = httplib.HTTPS(hp) 533 http = httplib.HTTPS(hp)
527 c = http._conn 534 c = http._conn
528 if h != c.host: 535 if h != c.host:
529 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host)) 536 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
530 if p != c.port: 537 if p != c.port:
531 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host)) 538 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
532 539
533 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
534 def test_main(verbose=None): 580 def test_main(verbose=None):
535 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, 581 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
536 HTTPSTimeoutTest, SourceAddressTest) 582 HTTPSTimeoutTest, SourceAddressTest, TunnelTests)
537 583
538 if __name__ == '__main__': 584 if __name__ == '__main__':
539 test_main() 585 test_main()
LEFTRIGHT

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