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

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

Issue 22417: PEP 476: verify HTTPS certificates by default
Left Patch Set: Created 4 years, 9 months ago
Right Patch Set: Created 4 years, 7 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/ssl.py ('k') | Lib/test/test_ssl.py » ('j') | 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 errno 1 import errno
2 from http import client 2 from http import client
3 import io 3 import io
4 import os 4 import os
5 import array 5 import array
6 import socket 6 import socket
7 7
8 import unittest 8 import unittest
9 TestCase = unittest.TestCase 9 TestCase = unittest.TestCase
10 10
11 from test import support 11 from test import support
12 12
13 here = os.path.dirname(__file__) 13 here = os.path.dirname(__file__)
14 # Self-signed cert file for 'localhost' 14 # Self-signed cert file for 'localhost'
15 CERT_localhost = os.path.join(here, 'keycert.pem') 15 CERT_localhost = os.path.join(here, 'keycert.pem')
16 # Self-signed cert file for 'fakehostname' 16 # Self-signed cert file for 'fakehostname'
17 CERT_fakehostname = os.path.join(here, 'keycert2.pem') 17 CERT_fakehostname = os.path.join(here, 'keycert2.pem')
18 # Root cert file (CA) for svn.python.org's cert 18 # Root cert file (CA) for svn.python.org's cert
19 CACERT_svn_python_org = os.path.join(here, 'https_svn_python_org_root.pem') 19 CACERT_svn_python_org = os.path.join(here, 'https_svn_python_org_root.pem')
20
21 # constants for testing chunked encoding
22 chunked_start = (
23 'HTTP/1.1 200 OK\r\n'
24 'Transfer-Encoding: chunked\r\n\r\n'
25 'a\r\n'
26 'hello worl\r\n'
27 '3\r\n'
28 'd! \r\n'
29 '8\r\n'
30 'and now \r\n'
31 '22\r\n'
32 'for something completely different\r\n'
33 )
34 chunked_expected = b'hello world! and now for something completely different'
35 chunk_extension = ";foo=bar"
36 last_chunk = "0\r\n"
37 last_chunk_extended = "0" + chunk_extension + "\r\n"
38 trailers = "X-Dummy: foo\r\nX-Dumm2: bar\r\n"
39 chunked_end = "\r\n"
20 40
21 HOST = support.HOST 41 HOST = support.HOST
22 42
23 class FakeSocket: 43 class FakeSocket:
24 def __init__(self, text, fileclass=io.BytesIO, host=None, port=None): 44 def __init__(self, text, fileclass=io.BytesIO, host=None, port=None):
25 if isinstance(text, str): 45 if isinstance(text, str):
26 text = text.encode("ascii") 46 text = text.encode("ascii")
27 self.text = text 47 self.text = text
28 self.fileclass = fileclass 48 self.fileclass = fileclass
29 self.data = b'' 49 self.data = b''
30 self.sendall_calls = 0 50 self.sendall_calls = 0
31 self.host = host 51 self.host = host
32 self.port = port 52 self.port = port
33 53
34 def sendall(self, data): 54 def sendall(self, data):
35 self.sendall_calls += 1 55 self.sendall_calls += 1
36 self.data += data 56 self.data += data
37 57
38 def makefile(self, mode, bufsize=None): 58 def makefile(self, mode, bufsize=None):
39 if mode != 'r' and mode != 'rb': 59 if mode != 'r' and mode != 'rb':
40 raise client.UnimplementedFileMode() 60 raise client.UnimplementedFileMode()
41 return self.fileclass(self.text) 61 # keep the file around so we can check how much was read from it
62 self.file = self.fileclass(self.text)
63 self.file.close = lambda:None #nerf close ()
64 return self.file
42 65
43 def close(self): 66 def close(self):
44 pass 67 pass
45 68
46 class EPipeSocket(FakeSocket): 69 class EPipeSocket(FakeSocket):
47 70
48 def __init__(self, text, pipe_trigger): 71 def __init__(self, text, pipe_trigger):
49 # When sendall() is called with pipe_trigger, raise EPIPE. 72 # When sendall() is called with pipe_trigger, raise EPIPE.
50 FakeSocket.__init__(self, text) 73 FakeSocket.__init__(self, text)
51 self.pipe_trigger = pipe_trigger 74 self.pipe_trigger = pipe_trigger
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 self.assertEqual(sock.data, expected) 451 self.assertEqual(sock.data, expected)
429 452
430 def test_send_type_error(self): 453 def test_send_type_error(self):
431 # See: Issue #12676 454 # See: Issue #12676
432 conn = client.HTTPConnection('example.com') 455 conn = client.HTTPConnection('example.com')
433 conn.sock = FakeSocket('') 456 conn.sock = FakeSocket('')
434 with self.assertRaises(TypeError): 457 with self.assertRaises(TypeError):
435 conn.request('POST', 'test', conn) 458 conn.request('POST', 'test', conn)
436 459
437 def test_chunked(self): 460 def test_chunked(self):
438 chunked_start = ( 461 expected = chunked_expected
439 'HTTP/1.1 200 OK\r\n' 462 sock = FakeSocket(chunked_start + last_chunk + chunked_end)
440 'Transfer-Encoding: chunked\r\n\r\n'
441 'a\r\n'
442 'hello worl\r\n'
443 '3\r\n'
444 'd! \r\n'
445 '8\r\n'
446 'and now \r\n'
447 '22\r\n'
448 'for something completely different\r\n'
449 )
450 expected = b'hello world! and now for something completely different'
451 sock = FakeSocket(chunked_start + '0\r\n')
452 resp = client.HTTPResponse(sock, method="GET") 463 resp = client.HTTPResponse(sock, method="GET")
453 resp.begin() 464 resp.begin()
454 self.assertEqual(resp.read(), expected) 465 self.assertEqual(resp.read(), expected)
455 resp.close() 466 resp.close()
456 467
457 # Various read sizes 468 # Various read sizes
458 for n in range(1, 12): 469 for n in range(1, 12):
459 sock = FakeSocket(chunked_start + '0\r\n') 470 sock = FakeSocket(chunked_start + last_chunk + chunked_end)
460 resp = client.HTTPResponse(sock, method="GET") 471 resp = client.HTTPResponse(sock, method="GET")
461 resp.begin() 472 resp.begin()
462 self.assertEqual(resp.read(n) + resp.read(n) + resp.read(), expected ) 473 self.assertEqual(resp.read(n) + resp.read(n) + resp.read(), expected )
463 resp.close() 474 resp.close()
464 475
465 for x in ('', 'foo\r\n'): 476 for x in ('', 'foo\r\n'):
466 sock = FakeSocket(chunked_start + x) 477 sock = FakeSocket(chunked_start + x)
467 resp = client.HTTPResponse(sock, method="GET") 478 resp = client.HTTPResponse(sock, method="GET")
468 resp.begin() 479 resp.begin()
469 try: 480 try:
470 resp.read() 481 resp.read()
471 except client.IncompleteRead as i: 482 except client.IncompleteRead as i:
472 self.assertEqual(i.partial, expected) 483 self.assertEqual(i.partial, expected)
473 expected_message = 'IncompleteRead(%d bytes read)' % len(expecte d) 484 expected_message = 'IncompleteRead(%d bytes read)' % len(expecte d)
474 self.assertEqual(repr(i), expected_message) 485 self.assertEqual(repr(i), expected_message)
475 self.assertEqual(str(i), expected_message) 486 self.assertEqual(str(i), expected_message)
476 else: 487 else:
477 self.fail('IncompleteRead expected') 488 self.fail('IncompleteRead expected')
478 finally: 489 finally:
479 resp.close() 490 resp.close()
480 491
481 def test_readinto_chunked(self): 492 def test_readinto_chunked(self):
482 chunked_start = ( 493
483 'HTTP/1.1 200 OK\r\n' 494 expected = chunked_expected
484 'Transfer-Encoding: chunked\r\n\r\n'
485 'a\r\n'
486 'hello worl\r\n'
487 '3\r\n'
488 'd! \r\n'
489 '8\r\n'
490 'and now \r\n'
491 '22\r\n'
492 'for something completely different\r\n'
493 )
494 expected = b'hello world! and now for something completely different'
495 nexpected = len(expected) 495 nexpected = len(expected)
496 b = bytearray(128) 496 b = bytearray(128)
497 497
498 sock = FakeSocket(chunked_start + '0\r\n') 498 sock = FakeSocket(chunked_start + last_chunk + chunked_end)
499 resp = client.HTTPResponse(sock, method="GET") 499 resp = client.HTTPResponse(sock, method="GET")
500 resp.begin() 500 resp.begin()
501 n = resp.readinto(b) 501 n = resp.readinto(b)
502 self.assertEqual(b[:nexpected], expected) 502 self.assertEqual(b[:nexpected], expected)
503 self.assertEqual(n, nexpected) 503 self.assertEqual(n, nexpected)
504 resp.close() 504 resp.close()
505 505
506 # Various read sizes 506 # Various read sizes
507 for n in range(1, 12): 507 for n in range(1, 12):
508 sock = FakeSocket(chunked_start + '0\r\n') 508 sock = FakeSocket(chunked_start + last_chunk + chunked_end)
509 resp = client.HTTPResponse(sock, method="GET") 509 resp = client.HTTPResponse(sock, method="GET")
510 resp.begin() 510 resp.begin()
511 m = memoryview(b) 511 m = memoryview(b)
512 i = resp.readinto(m[0:n]) 512 i = resp.readinto(m[0:n])
513 i += resp.readinto(m[i:n + i]) 513 i += resp.readinto(m[i:n + i])
514 i += resp.readinto(m[i:]) 514 i += resp.readinto(m[i:])
515 self.assertEqual(b[:nexpected], expected) 515 self.assertEqual(b[:nexpected], expected)
516 self.assertEqual(i, nexpected) 516 self.assertEqual(i, nexpected)
517 resp.close() 517 resp.close()
518 518
(...skipping 15 matching lines...) Expand all
534 534
535 def test_chunked_head(self): 535 def test_chunked_head(self):
536 chunked_start = ( 536 chunked_start = (
537 'HTTP/1.1 200 OK\r\n' 537 'HTTP/1.1 200 OK\r\n'
538 'Transfer-Encoding: chunked\r\n\r\n' 538 'Transfer-Encoding: chunked\r\n\r\n'
539 'a\r\n' 539 'a\r\n'
540 'hello world\r\n' 540 'hello world\r\n'
541 '1\r\n' 541 '1\r\n'
542 'd\r\n' 542 'd\r\n'
543 ) 543 )
544 sock = FakeSocket(chunked_start + '0\r\n') 544 sock = FakeSocket(chunked_start + last_chunk + chunked_end)
545 resp = client.HTTPResponse(sock, method="HEAD") 545 resp = client.HTTPResponse(sock, method="HEAD")
546 resp.begin() 546 resp.begin()
547 self.assertEqual(resp.read(), b'') 547 self.assertEqual(resp.read(), b'')
548 self.assertEqual(resp.status, 200) 548 self.assertEqual(resp.status, 200)
549 self.assertEqual(resp.reason, 'OK') 549 self.assertEqual(resp.reason, 'OK')
550 self.assertTrue(resp.isclosed()) 550 self.assertTrue(resp.isclosed())
551 self.assertFalse(resp.closed) 551 self.assertFalse(resp.closed)
552 resp.close() 552 resp.close()
553 self.assertTrue(resp.closed) 553 self.assertTrue(resp.closed)
554 554
555 def test_readinto_chunked_head(self): 555 def test_readinto_chunked_head(self):
556 chunked_start = ( 556 chunked_start = (
557 'HTTP/1.1 200 OK\r\n' 557 'HTTP/1.1 200 OK\r\n'
558 'Transfer-Encoding: chunked\r\n\r\n' 558 'Transfer-Encoding: chunked\r\n\r\n'
559 'a\r\n' 559 'a\r\n'
560 'hello world\r\n' 560 'hello world\r\n'
561 '1\r\n' 561 '1\r\n'
562 'd\r\n' 562 'd\r\n'
563 ) 563 )
564 sock = FakeSocket(chunked_start + '0\r\n') 564 sock = FakeSocket(chunked_start + last_chunk + chunked_end)
565 resp = client.HTTPResponse(sock, method="HEAD") 565 resp = client.HTTPResponse(sock, method="HEAD")
566 resp.begin() 566 resp.begin()
567 b = bytearray(5) 567 b = bytearray(5)
568 n = resp.readinto(b) 568 n = resp.readinto(b)
569 self.assertEqual(n, 0) 569 self.assertEqual(n, 0)
570 self.assertEqual(bytes(b), b'\x00'*5) 570 self.assertEqual(bytes(b), b'\x00'*5)
571 self.assertEqual(resp.status, 200) 571 self.assertEqual(resp.status, 200)
572 self.assertEqual(resp.reason, 'OK') 572 self.assertEqual(resp.reason, 'OK')
573 self.assertTrue(resp.isclosed()) 573 self.assertTrue(resp.isclosed())
574 self.assertFalse(resp.closed) 574 self.assertFalse(resp.closed)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 resp = client.HTTPResponse(FakeSocket(body)) 629 resp = client.HTTPResponse(FakeSocket(body))
630 self.assertRaises(client.LineTooLong, resp.begin) 630 self.assertRaises(client.LineTooLong, resp.begin)
631 631
632 def test_overflowing_chunked_line(self): 632 def test_overflowing_chunked_line(self):
633 body = ( 633 body = (
634 'HTTP/1.1 200 OK\r\n' 634 'HTTP/1.1 200 OK\r\n'
635 'Transfer-Encoding: chunked\r\n\r\n' 635 'Transfer-Encoding: chunked\r\n\r\n'
636 + '0' * 65536 + 'a\r\n' 636 + '0' * 65536 + 'a\r\n'
637 'hello world\r\n' 637 'hello world\r\n'
638 '0\r\n' 638 '0\r\n'
639 '\r\n'
639 ) 640 )
640 resp = client.HTTPResponse(FakeSocket(body)) 641 resp = client.HTTPResponse(FakeSocket(body))
641 resp.begin() 642 resp.begin()
642 self.assertRaises(client.LineTooLong, resp.read) 643 self.assertRaises(client.LineTooLong, resp.read)
643 644
644 def test_early_eof(self): 645 def test_early_eof(self):
645 # Test httpresponse with no \r\n termination, 646 # Test httpresponse with no \r\n termination,
646 body = "HTTP/1.1 200 Ok" 647 body = "HTTP/1.1 200 Ok"
647 sock = FakeSocket(body) 648 sock = FakeSocket(body)
648 resp = client.HTTPResponse(sock) 649 resp = client.HTTPResponse(sock)
(...skipping 19 matching lines...) Expand all
668 # For large payloads, it should send the headers and 669 # For large payloads, it should send the headers and
669 # then the body, resulting in more than one sendall() 670 # then the body, resulting in more than one sendall()
670 # call 671 # call
671 conn = client.HTTPConnection('example.com') 672 conn = client.HTTPConnection('example.com')
672 sock = FakeSocket(None) 673 sock = FakeSocket(None)
673 conn.sock = sock 674 conn.sock = sock
674 body = b'x' * conn.mss 675 body = b'x' * conn.mss
675 conn.request('POST', '/', body) 676 conn.request('POST', '/', body)
676 self.assertGreater(sock.sendall_calls, 1) 677 self.assertGreater(sock.sendall_calls, 1)
677 678
679 def test_chunked_extension(self):
680 extra = '3;foo=bar\r\n' + 'abc\r\n'
681 expected = chunked_expected + b'abc'
682
683 sock = FakeSocket(chunked_start + extra + last_chunk_extended + chunked_ end)
684 resp = client.HTTPResponse(sock, method="GET")
685 resp.begin()
686 self.assertEqual(resp.read(), expected)
687 resp.close()
688
689 def test_chunked_missing_end(self):
690 """some servers may serve up a short chunked encoding stream"""
691 expected = chunked_expected
692 sock = FakeSocket(chunked_start + last_chunk) #no terminating crlf
693 resp = client.HTTPResponse(sock, method="GET")
694 resp.begin()
695 self.assertEqual(resp.read(), expected)
696 resp.close()
697
698 def test_chunked_trailers(self):
699 """See that trailers are read and ignored"""
700 expected = chunked_expected
701 sock = FakeSocket(chunked_start + last_chunk + trailers + chunked_end)
702 resp = client.HTTPResponse(sock, method="GET")
703 resp.begin()
704 self.assertEqual(resp.read(), expected)
705 # we should have reached the end of the file
706 self.assertEqual(sock.file.read(100), b"") #we read to the end
707 resp.close()
708
709 def test_chunked_sync(self):
710 """Check that we don't read past the end of the chunked-encoding stream" ""
711 expected = chunked_expected
712 extradata = "extradata"
713 sock = FakeSocket(chunked_start + last_chunk + trailers + chunked_end + extradata)
714 resp = client.HTTPResponse(sock, method="GET")
715 resp.begin()
716 self.assertEqual(resp.read(), expected)
717 # the file should now have our extradata ready to be read
718 self.assertEqual(sock.file.read(100), extradata.encode("ascii")) #we rea d to the end
719 resp.close()
720
721 def test_content_length_sync(self):
722 """Check that we don't read past the end of the Content-Length stream"""
723 extradata = "extradata"
724 expected = b"Hello123\r\n"
725 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello123 \r\n' + extradata)
726 resp = client.HTTPResponse(sock, method="GET")
727 resp.begin()
728 self.assertEqual(resp.read(), expected)
729 # the file should now have our extradata ready to be read
730 self.assertEqual(sock.file.read(100), extradata.encode("ascii")) #we rea d to the end
731 resp.close()
732
733 class ExtendedReadTest(TestCase):
734 """
735 Test peek(), read1(), readline()
736 """
737 lines = (
738 'HTTP/1.1 200 OK\r\n'
739 '\r\n'
740 'hello world!\n'
741 'and now \n'
742 'for something completely different\n'
743 'foo'
744 )
745 lines_expected = lines[lines.find('hello'):].encode("ascii")
746 lines_chunked = (
747 'HTTP/1.1 200 OK\r\n'
748 'Transfer-Encoding: chunked\r\n\r\n'
749 'a\r\n'
750 'hello worl\r\n'
751 '3\r\n'
752 'd!\n\r\n'
753 '9\r\n'
754 'and now \n\r\n'
755 '23\r\n'
756 'for something completely different\n\r\n'
757 '3\r\n'
758 'foo\r\n'
759 '0\r\n' # terminating chunk
760 '\r\n' # end of trailers
761 )
762
763 def setUp(self):
764 sock = FakeSocket(self.lines)
765 resp = client.HTTPResponse(sock, method="GET")
766 resp.begin()
767 resp.fp = io.BufferedReader(resp.fp)
768 self.resp = resp
769
770
771
772 def test_peek(self):
773 resp = self.resp
774 # patch up the buffered peek so that it returns not too much stuff
775 oldpeek = resp.fp.peek
776 def mypeek(n=-1):
777 p = oldpeek(n)
778 if n >= 0:
779 return p[:n]
780 return p[:10]
781 resp.fp.peek = mypeek
782
783 all = []
784 while True:
785 # try a short peek
786 p = resp.peek(3)
787 if p:
788 self.assertGreater(len(p), 0)
789 # then unbounded peek
790 p2 = resp.peek()
791 self.assertGreaterEqual(len(p2), len(p))
792 self.assertTrue(p2.startswith(p))
793 next = resp.read(len(p2))
794 self.assertEqual(next, p2)
795 else:
796 next = resp.read()
797 self.assertFalse(next)
798 all.append(next)
799 if not next:
800 break
801 self.assertEqual(b"".join(all), self.lines_expected)
802
803 def test_readline(self):
804 resp = self.resp
805 self._verify_readline(self.resp.readline, self.lines_expected)
806
807 def _verify_readline(self, readline, expected):
808 all = []
809 while True:
810 # short readlines
811 line = readline(5)
812 if line and line != b"foo":
813 if len(line) < 5:
814 self.assertTrue(line.endswith(b"\n"))
815 all.append(line)
816 if not line:
817 break
818 self.assertEqual(b"".join(all), expected)
819
820 def test_read1(self):
821 resp = self.resp
822 def r():
823 res = resp.read1(4)
824 self.assertLessEqual(len(res), 4)
825 return res
826 readliner = Readliner(r)
827 self._verify_readline(readliner.readline, self.lines_expected)
828
829 def test_read1_unbounded(self):
830 resp = self.resp
831 all = []
832 while True:
833 data = resp.read1()
834 if not data:
835 break
836 all.append(data)
837 self.assertEqual(b"".join(all), self.lines_expected)
838
839 def test_read1_bounded(self):
840 resp = self.resp
841 all = []
842 while True:
843 data = resp.read1(10)
844 if not data:
845 break
846 self.assertLessEqual(len(data), 10)
847 all.append(data)
848 self.assertEqual(b"".join(all), self.lines_expected)
849
850 def test_read1_0(self):
851 self.assertEqual(self.resp.read1(0), b"")
852
853 def test_peek_0(self):
854 p = self.resp.peek(0)
855 self.assertLessEqual(0, len(p))
856
857 class ExtendedReadTestChunked(ExtendedReadTest):
858 """
859 Test peek(), read1(), readline() in chunked mode
860 """
861 lines = (
862 'HTTP/1.1 200 OK\r\n'
863 'Transfer-Encoding: chunked\r\n\r\n'
864 'a\r\n'
865 'hello worl\r\n'
866 '3\r\n'
867 'd!\n\r\n'
868 '9\r\n'
869 'and now \n\r\n'
870 '23\r\n'
871 'for something completely different\n\r\n'
872 '3\r\n'
873 'foo\r\n'
874 '0\r\n' # terminating chunk
875 '\r\n' # end of trailers
876 )
877
878
879 class Readliner:
880 """
881 a simple readline class that uses an arbitrary read function and buffering
882 """
883 def __init__(self, readfunc):
884 self.readfunc = readfunc
885 self.remainder = b""
886
887 def readline(self, limit):
888 data = []
889 datalen = 0
890 read = self.remainder
891 try:
892 while True:
893 idx = read.find(b'\n')
894 if idx != -1:
895 break
896 if datalen + len(read) >= limit:
897 idx = limit - datalen - 1
898 # read more data
899 data.append(read)
900 read = self.readfunc()
901 if not read:
902 idx = 0 #eof condition
903 break
904 idx += 1
905 data.append(read[:idx])
906 self.remainder = read[idx:]
907 return b"".join(data)
908 except:
909 self.remainder = b"".join(data)
910 raise
911
678 class OfflineTest(TestCase): 912 class OfflineTest(TestCase):
679 def test_responses(self): 913 def test_responses(self):
680 self.assertEqual(client.responses[client.NOT_FOUND], "Not Found") 914 self.assertEqual(client.responses[client.NOT_FOUND], "Not Found")
681 915
682 916
683 class SourceAddressTest(TestCase): 917 class SourceAddressTest(TestCase):
684 def setUp(self): 918 def setUp(self):
685 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 919 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
686 self.port = support.bind_port(self.serv) 920 self.port = support.bind_port(self.serv)
687 self.source_port = support.find_unused_port() 921 self.source_port = support.find_unused_port()
688 self.serv.listen(5) 922 self.serv.listen()
689 self.conn = None 923 self.conn = None
690 924
691 def tearDown(self): 925 def tearDown(self):
692 if self.conn: 926 if self.conn:
693 self.conn.close() 927 self.conn.close()
694 self.conn = None 928 self.conn = None
695 self.serv.close() 929 self.serv.close()
696 self.serv = None 930 self.serv = None
697 931
698 def testHTTPConnectionSourceAddress(self): 932 def testHTTPConnectionSourceAddress(self):
(...skipping 11 matching lines...) Expand all
710 # this code doesn't deal with setting up an active running SSL server 944 # this code doesn't deal with setting up an active running SSL server
711 # for an ssl_wrapped connect() to actually return from. 945 # for an ssl_wrapped connect() to actually return from.
712 946
713 947
714 class TimeoutTest(TestCase): 948 class TimeoutTest(TestCase):
715 PORT = None 949 PORT = None
716 950
717 def setUp(self): 951 def setUp(self):
718 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 952 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
719 TimeoutTest.PORT = support.bind_port(self.serv) 953 TimeoutTest.PORT = support.bind_port(self.serv)
720 self.serv.listen(5) 954 self.serv.listen()
721 955
722 def tearDown(self): 956 def tearDown(self):
723 self.serv.close() 957 self.serv.close()
724 self.serv = None 958 self.serv = None
725 959
726 def testTimeoutAttribute(self): 960 def testTimeoutAttribute(self):
727 # This will prove that the timeout gets through HTTPConnection 961 # This will prove that the timeout gets through HTTPConnection
728 # and into the socket. 962 # and into the socket.
729 963
730 # default -- use global socket timeout 964 # default -- use global socket timeout
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 1008
775 def _check_svn_python_org(self, resp): 1009 def _check_svn_python_org(self, resp):
776 # Just a simple check that everything went fine 1010 # Just a simple check that everything went fine
777 server_string = resp.getheader('server') 1011 server_string = resp.getheader('server')
778 self.assertIn('Apache', server_string) 1012 self.assertIn('Apache', server_string)
779 1013
780 def test_networked(self): 1014 def test_networked(self):
781 # Default settings: requires a valid cert from a trusted CA 1015 # Default settings: requires a valid cert from a trusted CA
782 import ssl 1016 import ssl
783 support.requires('network') 1017 support.requires('network')
784 with support.transient_internet('svn.python.org'): 1018 with support.transient_internet('self-signed.pythontest.net'):
785 h = client.HTTPSConnection('svn.python.org', 443) 1019 h = client.HTTPSConnection('self-signed.pythontest.net', 443)
786 with self.assertRaises(ssl.SSLError): 1020 with self.assertRaises(ssl.SSLError) as exc_info:
AntoinePitrou 2014/09/18 15:41:59 SSLError is vague, perhaps you can do further chec
787 h.request('GET', '/') 1021 h.request('GET', '/')
1022 self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAIL ED')
788 1023
789 def test_networked_noverification(self): 1024 def test_networked_noverification(self):
790 # Switch off cert verification 1025 # Switch off cert verification
791 import ssl 1026 import ssl
792 support.requires('network') 1027 support.requires('network')
793 with support.transient_internet('svn.python.org'): 1028 with support.transient_internet('self-signed.pythontest.net'):
794 context = ssl._create_unverified_context() 1029 context = ssl._create_unverified_context()
795 h = client.HTTPSConnection('svn.python.org', 443, context=context) 1030 h = client.HTTPSConnection('self-signed.pythontest.net', 443,
1031 context=context)
796 h.request('GET', '/') 1032 h.request('GET', '/')
797 resp = h.getresponse() 1033 resp = h.getresponse()
798 self._check_svn_python_org(resp) 1034 self.assertIn('nginx', resp.getheader('server'))
799 1035
800 def test_networked_trusted_by_default_cert(self): 1036 def test_networked_trusted_by_default_cert(self):
801 # Default settings: requires a valid cert from a trusted CA 1037 # Default settings: requires a valid cert from a trusted CA
AntoinePitrou 2014/09/18 15:41:59 The test will fail on any machine where we don't m
802 support.requires('network') 1038 support.requires('network')
803 with support.transient_internet('www.python.org'): 1039 with support.transient_internet('www.python.org'):
804 h = client.HTTPSConnection('www.python.org', 443) 1040 h = client.HTTPSConnection('www.python.org', 443)
805 h.request('GET', '/') 1041 h.request('GET', '/')
806 resp = h.getresponse() 1042 resp = h.getresponse()
807 content_type = resp.getheader('content-type') 1043 content_type = resp.getheader('content-type')
808 self.assertIn('text/html', content_type) 1044 self.assertIn('text/html', content_type)
809 1045
810 def test_networked_good_cert(self): 1046 def test_networked_good_cert(self):
811 # We feed a CA cert that validates the server's cert 1047 # We feed a CA cert that validates the server's cert
812 import ssl 1048 import ssl
813 support.requires('network') 1049 support.requires('network')
814 with support.transient_internet('svn.python.org'): 1050 with support.transient_internet('svn.python.org'):
815 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 1051 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
816 context.verify_mode = ssl.CERT_REQUIRED 1052 context.verify_mode = ssl.CERT_REQUIRED
817 context.load_verify_locations(CACERT_svn_python_org) 1053 context.load_verify_locations(CACERT_svn_python_org)
818 h = client.HTTPSConnection('svn.python.org', 443, context=context) 1054 h = client.HTTPSConnection('svn.python.org', 443, context=context)
819 h.request('GET', '/') 1055 h.request('GET', '/')
820 resp = h.getresponse() 1056 resp = h.getresponse()
821 self._check_svn_python_org(resp) 1057 self._check_svn_python_org(resp)
822 1058
823 def test_networked_bad_cert(self): 1059 def test_networked_bad_cert(self):
824 # We feed a "CA" cert that is unrelated to the server's cert 1060 # We feed a "CA" cert that is unrelated to the server's cert
825 import ssl 1061 import ssl
826 support.requires('network') 1062 support.requires('network')
827 with support.transient_internet('svn.python.org'): 1063 with support.transient_internet('self-signed.pythontest.net'):
828 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 1064 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
829 context.verify_mode = ssl.CERT_REQUIRED 1065 context.verify_mode = ssl.CERT_REQUIRED
830 context.load_verify_locations(CERT_localhost) 1066 context.load_verify_locations(CERT_localhost)
831 h = client.HTTPSConnection('svn.python.org', 443, context=context) 1067 h = client.HTTPSConnection('self-signed.pythontest.net', 443, contex t=context)
832 with self.assertRaises(ssl.SSLError): 1068 with self.assertRaises(ssl.SSLError) as exc_info:
833 h.request('GET', '/') 1069 h.request('GET', '/')
1070 self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAIL ED')
834 1071
835 def test_local_unknown_cert(self): 1072 def test_local_unknown_cert(self):
836 # The custom cert isn't known to the default trust bundle 1073 # The custom cert isn't known to the default trust bundle
837 import ssl 1074 import ssl
838 server = self.make_server(CERT_localhost) 1075 server = self.make_server(CERT_localhost)
839 h = client.HTTPSConnection('localhost', server.port) 1076 h = client.HTTPSConnection('localhost', server.port)
840 with self.assertRaises(ssl.SSLError): 1077 with self.assertRaises(ssl.SSLError) as exc_info:
AntoinePitrou 2014/09/18 15:41:59 Same as above here.
841 h.request('GET', '/') 1078 h.request('GET', '/')
842 del server 1079 self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED')
843 1080
844 def test_local_good_hostname(self): 1081 def test_local_good_hostname(self):
845 # The (valid) cert validates the HTTP hostname 1082 # The (valid) cert validates the HTTP hostname
846 import ssl 1083 import ssl
847 server = self.make_server(CERT_localhost) 1084 server = self.make_server(CERT_localhost)
848 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 1085 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
849 context.verify_mode = ssl.CERT_REQUIRED 1086 context.verify_mode = ssl.CERT_REQUIRED
850 context.load_verify_locations(CERT_localhost) 1087 context.load_verify_locations(CERT_localhost)
851 h = client.HTTPSConnection('localhost', server.port, context=context) 1088 h = client.HTTPSConnection('localhost', server.port, context=context)
852 h.request('GET', '/nonexistent') 1089 h.request('GET', '/nonexistent')
853 resp = h.getresponse() 1090 resp = h.getresponse()
854 self.assertEqual(resp.status, 404) 1091 self.assertEqual(resp.status, 404)
855 del server
856 1092
857 def test_local_bad_hostname(self): 1093 def test_local_bad_hostname(self):
858 # The (valid) cert doesn't validate the HTTP hostname 1094 # The (valid) cert doesn't validate the HTTP hostname
859 import ssl 1095 import ssl
860 server = self.make_server(CERT_fakehostname) 1096 server = self.make_server(CERT_fakehostname)
861 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 1097 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
862 context.verify_mode = ssl.CERT_REQUIRED 1098 context.verify_mode = ssl.CERT_REQUIRED
863 context.load_verify_locations(CERT_fakehostname) 1099 context.load_verify_locations(CERT_fakehostname)
864 h = client.HTTPSConnection('localhost', server.port, context=context) 1100 h = client.HTTPSConnection('localhost', server.port, context=context)
865 with self.assertRaises(ssl.CertificateError): 1101 with self.assertRaises(ssl.CertificateError):
866 h.request('GET', '/') 1102 h.request('GET', '/')
867 # Same with explicit check_hostname=True 1103 # Same with explicit check_hostname=True
868 h = client.HTTPSConnection('localhost', server.port, context=context, 1104 h = client.HTTPSConnection('localhost', server.port, context=context,
869 check_hostname=True) 1105 check_hostname=True)
870 with self.assertRaises(ssl.CertificateError): 1106 with self.assertRaises(ssl.CertificateError):
871 h.request('GET', '/') 1107 h.request('GET', '/')
872 # With check_hostname=False, the mismatching is ignored 1108 # With check_hostname=False, the mismatching is ignored
873 h = client.HTTPSConnection('localhost', server.port, context=context, 1109 h = client.HTTPSConnection('localhost', server.port, context=context,
874 check_hostname=False) 1110 check_hostname=False)
875 h.request('GET', '/nonexistent') 1111 h.request('GET', '/nonexistent')
876 resp = h.getresponse() 1112 resp = h.getresponse()
877 self.assertEqual(resp.status, 404) 1113 self.assertEqual(resp.status, 404)
878 del server
879 1114
880 @unittest.skipIf(not hasattr(client, 'HTTPSConnection'), 1115 @unittest.skipIf(not hasattr(client, 'HTTPSConnection'),
881 'http.client.HTTPSConnection not available') 1116 'http.client.HTTPSConnection not available')
882 def test_host_port(self): 1117 def test_host_port(self):
883 # Check invalid host_port 1118 # Check invalid host_port
884 1119
885 for hp in ("www.python.org:abc", "user:password@www.python.org"): 1120 for hp in ("www.python.org:abc", "user:password@www.python.org"):
886 self.assertRaises(client.InvalidURL, client.HTTPSConnection, hp) 1121 self.assertRaises(client.InvalidURL, client.HTTPSConnection, hp)
887 1122
888 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", 1123 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000",
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 conn.close() 1277 conn.close()
1043 conn.request('PUT', '/', '') 1278 conn.request('PUT', '/', '')
1044 self.assertEqual(conn.sock.host, 'proxy.com') 1279 self.assertEqual(conn.sock.host, 'proxy.com')
1045 self.assertEqual(conn.sock.port, 80) 1280 self.assertEqual(conn.sock.port, 80)
1046 self.assertTrue(b'CONNECT destination.com' in conn.sock.data) 1281 self.assertTrue(b'CONNECT destination.com' in conn.sock.data)
1047 self.assertTrue(b'Host: destination.com' in conn.sock.data) 1282 self.assertTrue(b'Host: destination.com' in conn.sock.data)
1048 1283
1049 def test_main(verbose=None): 1284 def test_main(verbose=None):
1050 support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, 1285 support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
1051 HTTPSTest, RequestBodyTest, SourceAddressTest, 1286 HTTPSTest, RequestBodyTest, SourceAddressTest,
1052 HTTPResponseTest, TunnelTests) 1287 HTTPResponseTest, ExtendedReadTest,
1288 ExtendedReadTestChunked, TunnelTests)
1053 1289
1054 if __name__ == '__main__': 1290 if __name__ == '__main__':
1055 test_main() 1291 test_main()
LEFTRIGHT

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