| Jeremy Hylton | 636950f | 2009-03-28 04:34:21 +0000 | [diff] [blame] | 1 | import errno | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 2 | from http import client | 
| Jeremy Hylton | 8fff792 | 2007-08-03 20:56:14 +0000 | [diff] [blame] | 3 | import io | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 4 | import os | 
| Antoine Pitrou | ead1d62 | 2009-09-29 18:44:53 +0000 | [diff] [blame] | 5 | import array | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 6 | import socket | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 7 |  | 
| Gregory P. Smith | b406637 | 2010-01-03 03:28:29 +0000 | [diff] [blame] | 8 | import unittest | 
 | 9 | TestCase = unittest.TestCase | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 10 |  | 
| Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 11 | from test import support | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 12 |  | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 13 | here = os.path.dirname(__file__) | 
 | 14 | # Self-signed cert file for 'localhost' | 
 | 15 | CERT_localhost = os.path.join(here, 'keycert.pem') | 
 | 16 | # Self-signed cert file for 'fakehostname' | 
 | 17 | CERT_fakehostname = os.path.join(here, 'keycert2.pem') | 
| Georg Brandl | fbaf931 | 2014-11-05 20:37:40 +0100 | [diff] [blame] | 18 | # Self-signed cert file for self-signed.pythontest.net | 
 | 19 | CERT_selfsigned_pythontestdotnet = os.path.join(here, 'selfsigned_pythontestdotnet.pem') | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 20 |  | 
| Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 21 | HOST = support.HOST | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 22 |  | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 23 | class FakeSocket: | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 24 |     def __init__(self, text, fileclass=io.BytesIO, host=None, port=None): | 
| Jeremy Hylton | 8fff792 | 2007-08-03 20:56:14 +0000 | [diff] [blame] | 25 |         if isinstance(text, str): | 
| Guido van Rossum | 39478e8 | 2007-08-27 17:23:59 +0000 | [diff] [blame] | 26 |             text = text.encode("ascii") | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 27 |         self.text = text | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 28 |         self.fileclass = fileclass | 
| Martin v. Löwis | dd5a860 | 2007-06-30 09:22:09 +0000 | [diff] [blame] | 29 |         self.data = b'' | 
| Antoine Pitrou | 90e4774 | 2013-01-02 22:10:47 +0100 | [diff] [blame] | 30 |         self.sendall_calls = 0 | 
| Serhiy Storchaka | b491e05 | 2014-12-01 13:07:45 +0200 | [diff] [blame] | 31 |         self.file_closed = False | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 32 |         self.host = host | 
 | 33 |         self.port = port | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 34 |  | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 35 |     def sendall(self, data): | 
| Antoine Pitrou | 90e4774 | 2013-01-02 22:10:47 +0100 | [diff] [blame] | 36 |         self.sendall_calls += 1 | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 37 |         self.data += data | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 38 |  | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 39 |     def makefile(self, mode, bufsize=None): | 
 | 40 |         if mode != 'r' and mode != 'rb': | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 41 |             raise client.UnimplementedFileMode() | 
| Serhiy Storchaka | b491e05 | 2014-12-01 13:07:45 +0200 | [diff] [blame] | 42 |         # keep the file around so we can check how much was read from it | 
 | 43 |         self.file = self.fileclass(self.text) | 
 | 44 |         self.file.close = self.file_close #nerf close () | 
 | 45 |         return self.file | 
 | 46 |  | 
 | 47 |     def file_close(self): | 
 | 48 |         self.file_closed = True | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 49 |  | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 50 |     def close(self): | 
 | 51 |         pass | 
 | 52 |  | 
| Jeremy Hylton | 636950f | 2009-03-28 04:34:21 +0000 | [diff] [blame] | 53 | class EPipeSocket(FakeSocket): | 
 | 54 |  | 
 | 55 |     def __init__(self, text, pipe_trigger): | 
 | 56 |         # When sendall() is called with pipe_trigger, raise EPIPE. | 
 | 57 |         FakeSocket.__init__(self, text) | 
 | 58 |         self.pipe_trigger = pipe_trigger | 
 | 59 |  | 
 | 60 |     def sendall(self, data): | 
 | 61 |         if self.pipe_trigger in data: | 
| Andrew Svetlov | 0832af6 | 2012-12-18 23:10:48 +0200 | [diff] [blame] | 62 |             raise OSError(errno.EPIPE, "gotcha") | 
| Jeremy Hylton | 636950f | 2009-03-28 04:34:21 +0000 | [diff] [blame] | 63 |         self.data += data | 
 | 64 |  | 
 | 65 |     def close(self): | 
 | 66 |         pass | 
 | 67 |  | 
| Serhiy Storchaka | 50254c5 | 2013-08-29 11:35:43 +0300 | [diff] [blame] | 68 | class NoEOFBytesIO(io.BytesIO): | 
 | 69 |     """Like BytesIO, but raises AssertionError on EOF. | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 70 |  | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 71 |     This is used below to test that http.client doesn't try to read | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 72 |     more from the underlying file than it should. | 
 | 73 |     """ | 
 | 74 |     def read(self, n=-1): | 
| Jeremy Hylton | 8fff792 | 2007-08-03 20:56:14 +0000 | [diff] [blame] | 75 |         data = io.BytesIO.read(self, n) | 
| Jeremy Hylton | da3f228 | 2007-08-29 17:26:34 +0000 | [diff] [blame] | 76 |         if data == b'': | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 77 |             raise AssertionError('caller tried to read past EOF') | 
 | 78 |         return data | 
 | 79 |  | 
 | 80 |     def readline(self, length=None): | 
| Jeremy Hylton | 8fff792 | 2007-08-03 20:56:14 +0000 | [diff] [blame] | 81 |         data = io.BytesIO.readline(self, length) | 
| Jeremy Hylton | da3f228 | 2007-08-29 17:26:34 +0000 | [diff] [blame] | 82 |         if data == b'': | 
| Jeremy Hylton | 121d34a | 2003-07-08 12:36:58 +0000 | [diff] [blame] | 83 |             raise AssertionError('caller tried to read past EOF') | 
 | 84 |         return data | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 85 |  | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 86 | class HeaderTests(TestCase): | 
 | 87 |     def test_auto_headers(self): | 
 | 88 |         # Some headers are added automatically, but should not be added by | 
 | 89 |         # .request() if they are explicitly set. | 
 | 90 |  | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 91 |         class HeaderCountingBuffer(list): | 
 | 92 |             def __init__(self): | 
 | 93 |                 self.count = {} | 
 | 94 |             def append(self, item): | 
| Guido van Rossum | 022c474 | 2007-08-29 02:00:20 +0000 | [diff] [blame] | 95 |                 kv = item.split(b':') | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 96 |                 if len(kv) > 1: | 
 | 97 |                     # item is a 'Key: Value' header string | 
| Martin v. Löwis | dd5a860 | 2007-06-30 09:22:09 +0000 | [diff] [blame] | 98 |                     lcKey = kv[0].decode('ascii').lower() | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 99 |                     self.count.setdefault(lcKey, 0) | 
 | 100 |                     self.count[lcKey] += 1 | 
 | 101 |                 list.append(self, item) | 
 | 102 |  | 
 | 103 |         for explicit_header in True, False: | 
 | 104 |             for header in 'Content-length', 'Host', 'Accept-encoding': | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 105 |                 conn = client.HTTPConnection('example.com') | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 106 |                 conn.sock = FakeSocket('blahblahblah') | 
 | 107 |                 conn._buffer = HeaderCountingBuffer() | 
 | 108 |  | 
 | 109 |                 body = 'spamspamspam' | 
 | 110 |                 headers = {} | 
 | 111 |                 if explicit_header: | 
 | 112 |                     headers[header] = str(len(body)) | 
 | 113 |                 conn.request('POST', '/', body, headers) | 
 | 114 |                 self.assertEqual(conn._buffer.count[header.lower()], 1) | 
 | 115 |  | 
| Senthil Kumaran | 5fa4a89 | 2012-05-19 16:58:09 +0800 | [diff] [blame] | 116 |     def test_content_length_0(self): | 
 | 117 |  | 
 | 118 |         class ContentLengthChecker(list): | 
 | 119 |             def __init__(self): | 
 | 120 |                 list.__init__(self) | 
 | 121 |                 self.content_length = None | 
 | 122 |             def append(self, item): | 
 | 123 |                 kv = item.split(b':', 1) | 
 | 124 |                 if len(kv) > 1 and kv[0].lower() == b'content-length': | 
 | 125 |                     self.content_length = kv[1].strip() | 
 | 126 |                 list.append(self, item) | 
 | 127 |  | 
 | 128 |         # POST with empty body | 
 | 129 |         conn = client.HTTPConnection('example.com') | 
 | 130 |         conn.sock = FakeSocket(None) | 
 | 131 |         conn._buffer = ContentLengthChecker() | 
 | 132 |         conn.request('POST', '/', '') | 
 | 133 |         self.assertEqual(conn._buffer.content_length, b'0', | 
 | 134 |                         'Header Content-Length not set') | 
 | 135 |  | 
 | 136 |         # PUT request with empty body | 
 | 137 |         conn = client.HTTPConnection('example.com') | 
 | 138 |         conn.sock = FakeSocket(None) | 
 | 139 |         conn._buffer = ContentLengthChecker() | 
 | 140 |         conn.request('PUT', '/', '') | 
 | 141 |         self.assertEqual(conn._buffer.content_length, b'0', | 
 | 142 |                         'Header Content-Length not set') | 
 | 143 |  | 
| Senthil Kumaran | 58d5dbf | 2010-10-03 18:22:42 +0000 | [diff] [blame] | 144 |     def test_putheader(self): | 
 | 145 |         conn = client.HTTPConnection('example.com') | 
 | 146 |         conn.sock = FakeSocket(None) | 
 | 147 |         conn.putrequest('GET','/') | 
 | 148 |         conn.putheader('Content-length', 42) | 
| Serhiy Storchaka | 25d8aea | 2014-02-08 14:50:08 +0200 | [diff] [blame] | 149 |         self.assertIn(b'Content-length: 42', conn._buffer) | 
| Senthil Kumaran | 58d5dbf | 2010-10-03 18:22:42 +0000 | [diff] [blame] | 150 |  | 
| Serhiy Storchaka | a112a8a | 2015-03-12 11:13:36 +0200 | [diff] [blame^] | 151 |         conn.putheader('Foo', ' bar ') | 
 | 152 |         self.assertIn(b'Foo:  bar ', conn._buffer) | 
 | 153 |         conn.putheader('Bar', '\tbaz\t') | 
 | 154 |         self.assertIn(b'Bar: \tbaz\t', conn._buffer) | 
 | 155 |         conn.putheader('Authorization', 'Bearer mytoken') | 
 | 156 |         self.assertIn(b'Authorization: Bearer mytoken', conn._buffer) | 
 | 157 |         conn.putheader('IterHeader', 'IterA', 'IterB') | 
 | 158 |         self.assertIn(b'IterHeader: IterA\r\n\tIterB', conn._buffer) | 
 | 159 |         conn.putheader('LatinHeader', b'\xFF') | 
 | 160 |         self.assertIn(b'LatinHeader: \xFF', conn._buffer) | 
 | 161 |         conn.putheader('Utf8Header', b'\xc3\x80') | 
 | 162 |         self.assertIn(b'Utf8Header: \xc3\x80', conn._buffer) | 
 | 163 |         conn.putheader('C1-Control', b'next\x85line') | 
 | 164 |         self.assertIn(b'C1-Control: next\x85line', conn._buffer) | 
 | 165 |         conn.putheader('Embedded-Fold-Space', 'is\r\n allowed') | 
 | 166 |         self.assertIn(b'Embedded-Fold-Space: is\r\n allowed', conn._buffer) | 
 | 167 |         conn.putheader('Embedded-Fold-Tab', 'is\r\n\tallowed') | 
 | 168 |         self.assertIn(b'Embedded-Fold-Tab: is\r\n\tallowed', conn._buffer) | 
 | 169 |         conn.putheader('Key Space', 'value') | 
 | 170 |         self.assertIn(b'Key Space: value', conn._buffer) | 
 | 171 |         conn.putheader('KeySpace ', 'value') | 
 | 172 |         self.assertIn(b'KeySpace : value', conn._buffer) | 
 | 173 |         conn.putheader(b'Nonbreak\xa0Space', 'value') | 
 | 174 |         self.assertIn(b'Nonbreak\xa0Space: value', conn._buffer) | 
 | 175 |         conn.putheader(b'\xa0NonbreakSpace', 'value') | 
 | 176 |         self.assertIn(b'\xa0NonbreakSpace: value', conn._buffer) | 
 | 177 |  | 
| Senthil Kumaran | 74ebd9e | 2010-11-13 12:27:49 +0000 | [diff] [blame] | 178 |     def test_ipv6host_header(self): | 
 | 179 |         # Default host header on IPv6 transaction should wrapped by [] if | 
 | 180 |         # its actual IPv6 address | 
 | 181 |         expected = b'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \ | 
 | 182 |                    b'Accept-Encoding: identity\r\n\r\n' | 
 | 183 |         conn = client.HTTPConnection('[2001::]:81') | 
 | 184 |         sock = FakeSocket('') | 
 | 185 |         conn.sock = sock | 
 | 186 |         conn.request('GET', '/foo') | 
 | 187 |         self.assertTrue(sock.data.startswith(expected)) | 
 | 188 |  | 
 | 189 |         expected = b'GET /foo HTTP/1.1\r\nHost: [2001:102A::]\r\n' \ | 
 | 190 |                    b'Accept-Encoding: identity\r\n\r\n' | 
 | 191 |         conn = client.HTTPConnection('[2001:102A::]') | 
 | 192 |         sock = FakeSocket('') | 
 | 193 |         conn.sock = sock | 
 | 194 |         conn.request('GET', '/foo') | 
 | 195 |         self.assertTrue(sock.data.startswith(expected)) | 
 | 196 |  | 
| Benjamin Peterson | 155ceaa | 2015-01-25 23:30:30 -0500 | [diff] [blame] | 197 |     def test_malformed_headers_coped_with(self): | 
 | 198 |         # Issue 19996 | 
 | 199 |         body = "HTTP/1.1 200 OK\r\nFirst: val\r\n: nval\r\nSecond: val\r\n\r\n" | 
 | 200 |         sock = FakeSocket(body) | 
 | 201 |         resp = client.HTTPResponse(sock) | 
 | 202 |         resp.begin() | 
 | 203 |  | 
 | 204 |         self.assertEqual(resp.getheader('First'), 'val') | 
 | 205 |         self.assertEqual(resp.getheader('Second'), 'val') | 
 | 206 |  | 
| Serhiy Storchaka | a112a8a | 2015-03-12 11:13:36 +0200 | [diff] [blame^] | 207 |     def test_invalid_headers(self): | 
 | 208 |         conn = client.HTTPConnection('example.com') | 
 | 209 |         conn.sock = FakeSocket('') | 
 | 210 |         conn.putrequest('GET', '/') | 
 | 211 |  | 
 | 212 |         # http://tools.ietf.org/html/rfc7230#section-3.2.4, whitespace is no | 
 | 213 |         # longer allowed in header names | 
 | 214 |         cases = ( | 
 | 215 |             (b'Invalid\r\nName', b'ValidValue'), | 
 | 216 |             (b'Invalid\rName', b'ValidValue'), | 
 | 217 |             (b'Invalid\nName', b'ValidValue'), | 
 | 218 |             (b'\r\nInvalidName', b'ValidValue'), | 
 | 219 |             (b'\rInvalidName', b'ValidValue'), | 
 | 220 |             (b'\nInvalidName', b'ValidValue'), | 
 | 221 |             (b' InvalidName', b'ValidValue'), | 
 | 222 |             (b'\tInvalidName', b'ValidValue'), | 
 | 223 |             (b'Invalid:Name', b'ValidValue'), | 
 | 224 |             (b':InvalidName', b'ValidValue'), | 
 | 225 |             (b'ValidName', b'Invalid\r\nValue'), | 
 | 226 |             (b'ValidName', b'Invalid\rValue'), | 
 | 227 |             (b'ValidName', b'Invalid\nValue'), | 
 | 228 |             (b'ValidName', b'InvalidValue\r\n'), | 
 | 229 |             (b'ValidName', b'InvalidValue\r'), | 
 | 230 |             (b'ValidName', b'InvalidValue\n'), | 
 | 231 |         ) | 
 | 232 |         for name, value in cases: | 
 | 233 |             with self.subTest((name, value)): | 
 | 234 |                 with self.assertRaisesRegex(ValueError, 'Invalid header'): | 
 | 235 |                     conn.putheader(name, value) | 
 | 236 |  | 
| Senthil Kumaran | 58d5dbf | 2010-10-03 18:22:42 +0000 | [diff] [blame] | 237 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 238 | class BasicTest(TestCase): | 
 | 239 |     def test_status_lines(self): | 
 | 240 |         # Test HTTP status lines | 
| Jeremy Hylton | 79fa2b6 | 2001-04-13 14:57:44 +0000 | [diff] [blame] | 241 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 242 |         body = "HTTP/1.1 200 Ok\r\n\r\nText" | 
 | 243 |         sock = FakeSocket(body) | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 244 |         resp = client.HTTPResponse(sock) | 
| Jeremy Hylton | ba60319 | 2003-01-23 18:02:20 +0000 | [diff] [blame] | 245 |         resp.begin() | 
| Serhiy Storchaka | 1c84ac1 | 2013-12-17 21:50:02 +0200 | [diff] [blame] | 246 |         self.assertEqual(resp.read(0), b'')  # Issue #20007 | 
 | 247 |         self.assertFalse(resp.isclosed()) | 
 | 248 |         self.assertFalse(resp.closed) | 
| Jeremy Hylton | 8fff792 | 2007-08-03 20:56:14 +0000 | [diff] [blame] | 249 |         self.assertEqual(resp.read(), b"Text") | 
| Guido van Rossum | 8ce8a78 | 2007-11-01 19:42:39 +0000 | [diff] [blame] | 250 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b5b9c8c | 2013-02-06 10:31:57 +0200 | [diff] [blame] | 251 |         self.assertFalse(resp.closed) | 
 | 252 |         resp.close() | 
 | 253 |         self.assertTrue(resp.closed) | 
| Jeremy Hylton | ba60319 | 2003-01-23 18:02:20 +0000 | [diff] [blame] | 254 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 255 |         body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText" | 
 | 256 |         sock = FakeSocket(body) | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 257 |         resp = client.HTTPResponse(sock) | 
 | 258 |         self.assertRaises(client.BadStatusLine, resp.begin) | 
| Jeremy Hylton | ba60319 | 2003-01-23 18:02:20 +0000 | [diff] [blame] | 259 |  | 
| Benjamin Peterson | 11dbfd4 | 2010-03-21 22:50:04 +0000 | [diff] [blame] | 260 |     def test_bad_status_repr(self): | 
 | 261 |         exc = client.BadStatusLine('') | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 262 |         self.assertEqual(repr(exc), '''BadStatusLine("\'\'",)''') | 
| Benjamin Peterson | 11dbfd4 | 2010-03-21 22:50:04 +0000 | [diff] [blame] | 263 |  | 
| Guido van Rossum | 8ce8a78 | 2007-11-01 19:42:39 +0000 | [diff] [blame] | 264 |     def test_partial_reads(self): | 
| Antoine Pitrou | 084daa2 | 2012-12-15 19:11:54 +0100 | [diff] [blame] | 265 |         # if we have a length, the system knows when to close itself | 
| Guido van Rossum | 8ce8a78 | 2007-11-01 19:42:39 +0000 | [diff] [blame] | 266 |         # same behaviour than when we read the whole thing with read() | 
 | 267 |         body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText" | 
 | 268 |         sock = FakeSocket(body) | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 269 |         resp = client.HTTPResponse(sock) | 
| Guido van Rossum | 8ce8a78 | 2007-11-01 19:42:39 +0000 | [diff] [blame] | 270 |         resp.begin() | 
 | 271 |         self.assertEqual(resp.read(2), b'Te') | 
 | 272 |         self.assertFalse(resp.isclosed()) | 
 | 273 |         self.assertEqual(resp.read(2), b'xt') | 
 | 274 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b5b9c8c | 2013-02-06 10:31:57 +0200 | [diff] [blame] | 275 |         self.assertFalse(resp.closed) | 
 | 276 |         resp.close() | 
 | 277 |         self.assertTrue(resp.closed) | 
| Guido van Rossum | 8ce8a78 | 2007-11-01 19:42:39 +0000 | [diff] [blame] | 278 |  | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 279 |     def test_partial_readintos(self): | 
| Antoine Pitrou | d20e774 | 2012-12-15 19:22:30 +0100 | [diff] [blame] | 280 |         # if we have a length, the system knows when to close itself | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 281 |         # same behaviour than when we read the whole thing with read() | 
 | 282 |         body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText" | 
 | 283 |         sock = FakeSocket(body) | 
 | 284 |         resp = client.HTTPResponse(sock) | 
 | 285 |         resp.begin() | 
 | 286 |         b = bytearray(2) | 
 | 287 |         n = resp.readinto(b) | 
 | 288 |         self.assertEqual(n, 2) | 
 | 289 |         self.assertEqual(bytes(b), b'Te') | 
 | 290 |         self.assertFalse(resp.isclosed()) | 
 | 291 |         n = resp.readinto(b) | 
 | 292 |         self.assertEqual(n, 2) | 
 | 293 |         self.assertEqual(bytes(b), b'xt') | 
 | 294 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b6c86fd | 2013-02-06 10:35:40 +0200 | [diff] [blame] | 295 |         self.assertFalse(resp.closed) | 
 | 296 |         resp.close() | 
 | 297 |         self.assertTrue(resp.closed) | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 298 |  | 
| Antoine Pitrou | 084daa2 | 2012-12-15 19:11:54 +0100 | [diff] [blame] | 299 |     def test_partial_reads_no_content_length(self): | 
 | 300 |         # when no length is present, the socket should be gracefully closed when | 
 | 301 |         # all data was read | 
 | 302 |         body = "HTTP/1.1 200 Ok\r\n\r\nText" | 
 | 303 |         sock = FakeSocket(body) | 
 | 304 |         resp = client.HTTPResponse(sock) | 
 | 305 |         resp.begin() | 
 | 306 |         self.assertEqual(resp.read(2), b'Te') | 
 | 307 |         self.assertFalse(resp.isclosed()) | 
 | 308 |         self.assertEqual(resp.read(2), b'xt') | 
 | 309 |         self.assertEqual(resp.read(1), b'') | 
 | 310 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b5b9c8c | 2013-02-06 10:31:57 +0200 | [diff] [blame] | 311 |         self.assertFalse(resp.closed) | 
 | 312 |         resp.close() | 
 | 313 |         self.assertTrue(resp.closed) | 
| Antoine Pitrou | 084daa2 | 2012-12-15 19:11:54 +0100 | [diff] [blame] | 314 |  | 
| Antoine Pitrou | d20e774 | 2012-12-15 19:22:30 +0100 | [diff] [blame] | 315 |     def test_partial_readintos_no_content_length(self): | 
 | 316 |         # when no length is present, the socket should be gracefully closed when | 
 | 317 |         # all data was read | 
 | 318 |         body = "HTTP/1.1 200 Ok\r\n\r\nText" | 
 | 319 |         sock = FakeSocket(body) | 
 | 320 |         resp = client.HTTPResponse(sock) | 
 | 321 |         resp.begin() | 
 | 322 |         b = bytearray(2) | 
 | 323 |         n = resp.readinto(b) | 
 | 324 |         self.assertEqual(n, 2) | 
 | 325 |         self.assertEqual(bytes(b), b'Te') | 
 | 326 |         self.assertFalse(resp.isclosed()) | 
 | 327 |         n = resp.readinto(b) | 
 | 328 |         self.assertEqual(n, 2) | 
 | 329 |         self.assertEqual(bytes(b), b'xt') | 
 | 330 |         n = resp.readinto(b) | 
 | 331 |         self.assertEqual(n, 0) | 
 | 332 |         self.assertTrue(resp.isclosed()) | 
 | 333 |  | 
| Antoine Pitrou | beec61a | 2013-02-02 22:49:34 +0100 | [diff] [blame] | 334 |     def test_partial_reads_incomplete_body(self): | 
 | 335 |         # if the server shuts down the connection before the whole | 
 | 336 |         # content-length is delivered, the socket is gracefully closed | 
 | 337 |         body = "HTTP/1.1 200 Ok\r\nContent-Length: 10\r\n\r\nText" | 
 | 338 |         sock = FakeSocket(body) | 
 | 339 |         resp = client.HTTPResponse(sock) | 
 | 340 |         resp.begin() | 
 | 341 |         self.assertEqual(resp.read(2), b'Te') | 
 | 342 |         self.assertFalse(resp.isclosed()) | 
 | 343 |         self.assertEqual(resp.read(2), b'xt') | 
 | 344 |         self.assertEqual(resp.read(1), b'') | 
 | 345 |         self.assertTrue(resp.isclosed()) | 
 | 346 |  | 
| Antoine Pitrou | 6a35e18 | 2013-02-02 23:04:56 +0100 | [diff] [blame] | 347 |     def test_partial_readintos_incomplete_body(self): | 
 | 348 |         # if the server shuts down the connection before the whole | 
 | 349 |         # content-length is delivered, the socket is gracefully closed | 
 | 350 |         body = "HTTP/1.1 200 Ok\r\nContent-Length: 10\r\n\r\nText" | 
 | 351 |         sock = FakeSocket(body) | 
 | 352 |         resp = client.HTTPResponse(sock) | 
 | 353 |         resp.begin() | 
 | 354 |         b = bytearray(2) | 
 | 355 |         n = resp.readinto(b) | 
 | 356 |         self.assertEqual(n, 2) | 
 | 357 |         self.assertEqual(bytes(b), b'Te') | 
 | 358 |         self.assertFalse(resp.isclosed()) | 
 | 359 |         n = resp.readinto(b) | 
 | 360 |         self.assertEqual(n, 2) | 
 | 361 |         self.assertEqual(bytes(b), b'xt') | 
 | 362 |         n = resp.readinto(b) | 
 | 363 |         self.assertEqual(n, 0) | 
 | 364 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b5b9c8c | 2013-02-06 10:31:57 +0200 | [diff] [blame] | 365 |         self.assertFalse(resp.closed) | 
 | 366 |         resp.close() | 
 | 367 |         self.assertTrue(resp.closed) | 
| Antoine Pitrou | 6a35e18 | 2013-02-02 23:04:56 +0100 | [diff] [blame] | 368 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 369 |     def test_host_port(self): | 
 | 370 |         # Check invalid host_port | 
| Jeremy Hylton | ba60319 | 2003-01-23 18:02:20 +0000 | [diff] [blame] | 371 |  | 
| Łukasz Langa | a5a9a9c | 2011-10-18 21:17:39 +0200 | [diff] [blame] | 372 |         for hp in ("www.python.org:abc", "user:password@www.python.org"): | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 373 |             self.assertRaises(client.InvalidURL, client.HTTPConnection, hp) | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 374 |  | 
| Jeremy Hylton | 3a38c91 | 2007-08-14 17:08:07 +0000 | [diff] [blame] | 375 |         for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", | 
 | 376 |                           "fe80::207:e9ff:fe9b", 8000), | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 377 |                          ("www.python.org:80", "www.python.org", 80), | 
| Łukasz Langa | a5a9a9c | 2011-10-18 21:17:39 +0200 | [diff] [blame] | 378 |                          ("www.python.org:", "www.python.org", 80), | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 379 |                          ("www.python.org", "www.python.org", 80), | 
| Łukasz Langa | a5a9a9c | 2011-10-18 21:17:39 +0200 | [diff] [blame] | 380 |                          ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80), | 
 | 381 |                          ("[fe80::207:e9ff:fe9b]:", "fe80::207:e9ff:fe9b", 80)): | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 382 |             c = client.HTTPConnection(hp) | 
| Jeremy Hylton | 3a38c91 | 2007-08-14 17:08:07 +0000 | [diff] [blame] | 383 |             self.assertEqual(h, c.host) | 
 | 384 |             self.assertEqual(p, c.port) | 
| Skip Montanaro | 10e6e0e | 2004-09-14 16:32:02 +0000 | [diff] [blame] | 385 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 386 |     def test_response_headers(self): | 
 | 387 |         # test response with multiple message headers with the same field name. | 
 | 388 |         text = ('HTTP/1.1 200 OK\r\n' | 
| Jeremy Hylton | 3a38c91 | 2007-08-14 17:08:07 +0000 | [diff] [blame] | 389 |                 'Set-Cookie: Customer="WILE_E_COYOTE"; ' | 
 | 390 |                 'Version="1"; Path="/acme"\r\n' | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 391 |                 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";' | 
 | 392 |                 ' Path="/acme"\r\n' | 
 | 393 |                 '\r\n' | 
 | 394 |                 'No body\r\n') | 
 | 395 |         hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"' | 
 | 396 |                ', ' | 
 | 397 |                'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"') | 
 | 398 |         s = FakeSocket(text) | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 399 |         r = client.HTTPResponse(s) | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 400 |         r.begin() | 
 | 401 |         cookies = r.getheader("Set-Cookie") | 
| Jeremy Hylton | 3a38c91 | 2007-08-14 17:08:07 +0000 | [diff] [blame] | 402 |         self.assertEqual(cookies, hdr) | 
| Jeremy Hylton | ba60319 | 2003-01-23 18:02:20 +0000 | [diff] [blame] | 403 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 404 |     def test_read_head(self): | 
 | 405 |         # Test that the library doesn't attempt to read any data | 
 | 406 |         # from a HEAD request.  (Tickles SF bug #622042.) | 
 | 407 |         sock = FakeSocket( | 
 | 408 |             'HTTP/1.1 200 OK\r\n' | 
 | 409 |             'Content-Length: 14432\r\n' | 
 | 410 |             '\r\n', | 
| Serhiy Storchaka | 50254c5 | 2013-08-29 11:35:43 +0300 | [diff] [blame] | 411 |             NoEOFBytesIO) | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 412 |         resp = client.HTTPResponse(sock, method="HEAD") | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 413 |         resp.begin() | 
| Guido van Rossum | a00f123 | 2007-09-12 19:43:09 +0000 | [diff] [blame] | 414 |         if resp.read(): | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 415 |             self.fail("Did not expect response from HEAD request") | 
| Jeremy Hylton | c1b2cb9 | 2003-05-05 16:13:58 +0000 | [diff] [blame] | 416 |  | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 417 |     def test_readinto_head(self): | 
 | 418 |         # Test that the library doesn't attempt to read any data | 
 | 419 |         # from a HEAD request.  (Tickles SF bug #622042.) | 
 | 420 |         sock = FakeSocket( | 
 | 421 |             'HTTP/1.1 200 OK\r\n' | 
 | 422 |             'Content-Length: 14432\r\n' | 
 | 423 |             '\r\n', | 
| Serhiy Storchaka | 50254c5 | 2013-08-29 11:35:43 +0300 | [diff] [blame] | 424 |             NoEOFBytesIO) | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 425 |         resp = client.HTTPResponse(sock, method="HEAD") | 
 | 426 |         resp.begin() | 
 | 427 |         b = bytearray(5) | 
 | 428 |         if resp.readinto(b) != 0: | 
 | 429 |             self.fail("Did not expect response from HEAD request") | 
 | 430 |         self.assertEqual(bytes(b), b'\x00'*5) | 
 | 431 |  | 
| Georg Brandl | bf3f8eb | 2013-10-27 07:34:48 +0100 | [diff] [blame] | 432 |     def test_too_many_headers(self): | 
 | 433 |         headers = '\r\n'.join('Header%d: foo' % i | 
 | 434 |                               for i in range(client._MAXHEADERS + 1)) + '\r\n' | 
 | 435 |         text = ('HTTP/1.1 200 OK\r\n' + headers) | 
 | 436 |         s = FakeSocket(text) | 
 | 437 |         r = client.HTTPResponse(s) | 
 | 438 |         self.assertRaisesRegex(client.HTTPException, | 
 | 439 |                                r"got more than \d+ headers", r.begin) | 
 | 440 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 441 |     def test_send_file(self): | 
| Guido van Rossum | 022c474 | 2007-08-29 02:00:20 +0000 | [diff] [blame] | 442 |         expected = (b'GET /foo HTTP/1.1\r\nHost: example.com\r\n' | 
 | 443 |                     b'Accept-Encoding: identity\r\nContent-Length:') | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 444 |  | 
| Brett Cannon | 77b7de6 | 2010-10-29 23:31:11 +0000 | [diff] [blame] | 445 |         with open(__file__, 'rb') as body: | 
 | 446 |             conn = client.HTTPConnection('example.com') | 
 | 447 |             sock = FakeSocket(body) | 
 | 448 |             conn.sock = sock | 
 | 449 |             conn.request('GET', '/foo', body) | 
 | 450 |             self.assertTrue(sock.data.startswith(expected), '%r != %r' % | 
 | 451 |                     (sock.data[:len(expected)], expected)) | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 452 |  | 
| Antoine Pitrou | ead1d62 | 2009-09-29 18:44:53 +0000 | [diff] [blame] | 453 |     def test_send(self): | 
 | 454 |         expected = b'this is a test this is only a test' | 
 | 455 |         conn = client.HTTPConnection('example.com') | 
 | 456 |         sock = FakeSocket(None) | 
 | 457 |         conn.sock = sock | 
 | 458 |         conn.send(expected) | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 459 |         self.assertEqual(expected, sock.data) | 
| Antoine Pitrou | ead1d62 | 2009-09-29 18:44:53 +0000 | [diff] [blame] | 460 |         sock.data = b'' | 
 | 461 |         conn.send(array.array('b', expected)) | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 462 |         self.assertEqual(expected, sock.data) | 
| Antoine Pitrou | ead1d62 | 2009-09-29 18:44:53 +0000 | [diff] [blame] | 463 |         sock.data = b'' | 
 | 464 |         conn.send(io.BytesIO(expected)) | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 465 |         self.assertEqual(expected, sock.data) | 
| Antoine Pitrou | ead1d62 | 2009-09-29 18:44:53 +0000 | [diff] [blame] | 466 |  | 
| Andrew Svetlov | 7b2c8bb | 2013-04-12 22:49:19 +0300 | [diff] [blame] | 467 |     def test_send_updating_file(self): | 
 | 468 |         def data(): | 
 | 469 |             yield 'data' | 
 | 470 |             yield None | 
 | 471 |             yield 'data_two' | 
 | 472 |  | 
 | 473 |         class UpdatingFile(): | 
 | 474 |             mode = 'r' | 
 | 475 |             d = data() | 
 | 476 |             def read(self, blocksize=-1): | 
 | 477 |                 return self.d.__next__() | 
 | 478 |  | 
 | 479 |         expected = b'data' | 
 | 480 |  | 
 | 481 |         conn = client.HTTPConnection('example.com') | 
 | 482 |         sock = FakeSocket("") | 
 | 483 |         conn.sock = sock | 
 | 484 |         conn.send(UpdatingFile()) | 
 | 485 |         self.assertEqual(sock.data, expected) | 
 | 486 |  | 
 | 487 |  | 
| Senthil Kumaran | 7bc0d87 | 2010-12-19 10:49:52 +0000 | [diff] [blame] | 488 |     def test_send_iter(self): | 
 | 489 |         expected = b'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \ | 
 | 490 |                    b'Accept-Encoding: identity\r\nContent-Length: 11\r\n' \ | 
 | 491 |                    b'\r\nonetwothree' | 
 | 492 |  | 
 | 493 |         def body(): | 
 | 494 |             yield b"one" | 
 | 495 |             yield b"two" | 
 | 496 |             yield b"three" | 
 | 497 |  | 
 | 498 |         conn = client.HTTPConnection('example.com') | 
 | 499 |         sock = FakeSocket("") | 
 | 500 |         conn.sock = sock | 
 | 501 |         conn.request('GET', '/foo', body(), {'Content-Length': '11'}) | 
| Victor Stinner | 04ba966 | 2011-01-04 00:04:46 +0000 | [diff] [blame] | 502 |         self.assertEqual(sock.data, expected) | 
| Senthil Kumaran | 7bc0d87 | 2010-12-19 10:49:52 +0000 | [diff] [blame] | 503 |  | 
| Senthil Kumaran | eb71ad4 | 2011-08-02 18:33:41 +0800 | [diff] [blame] | 504 |     def test_send_type_error(self): | 
 | 505 |         # See: Issue #12676 | 
 | 506 |         conn = client.HTTPConnection('example.com') | 
 | 507 |         conn.sock = FakeSocket('') | 
 | 508 |         with self.assertRaises(TypeError): | 
 | 509 |             conn.request('POST', 'test', conn) | 
 | 510 |  | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 511 |     def test_chunked(self): | 
 | 512 |         chunked_start = ( | 
 | 513 |             'HTTP/1.1 200 OK\r\n' | 
 | 514 |             'Transfer-Encoding: chunked\r\n\r\n' | 
 | 515 |             'a\r\n' | 
 | 516 |             'hello worl\r\n' | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 517 |             '3\r\n' | 
 | 518 |             'd! \r\n' | 
 | 519 |             '8\r\n' | 
 | 520 |             'and now \r\n' | 
 | 521 |             '22\r\n' | 
 | 522 |             'for something completely different\r\n' | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 523 |         ) | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 524 |         expected = b'hello world! and now for something completely different' | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 525 |         sock = FakeSocket(chunked_start + '0\r\n') | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 526 |         resp = client.HTTPResponse(sock, method="GET") | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 527 |         resp.begin() | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 528 |         self.assertEqual(resp.read(), expected) | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 529 |         resp.close() | 
 | 530 |  | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 531 |         # Various read sizes | 
 | 532 |         for n in range(1, 12): | 
 | 533 |             sock = FakeSocket(chunked_start + '0\r\n') | 
 | 534 |             resp = client.HTTPResponse(sock, method="GET") | 
 | 535 |             resp.begin() | 
 | 536 |             self.assertEqual(resp.read(n) + resp.read(n) + resp.read(), expected) | 
 | 537 |             resp.close() | 
 | 538 |  | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 539 |         for x in ('', 'foo\r\n'): | 
 | 540 |             sock = FakeSocket(chunked_start + x) | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 541 |             resp = client.HTTPResponse(sock, method="GET") | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 542 |             resp.begin() | 
 | 543 |             try: | 
 | 544 |                 resp.read() | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 545 |             except client.IncompleteRead as i: | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 546 |                 self.assertEqual(i.partial, expected) | 
 | 547 |                 expected_message = 'IncompleteRead(%d bytes read)' % len(expected) | 
 | 548 |                 self.assertEqual(repr(i), expected_message) | 
 | 549 |                 self.assertEqual(str(i), expected_message) | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 550 |             else: | 
 | 551 |                 self.fail('IncompleteRead expected') | 
 | 552 |             finally: | 
 | 553 |                 resp.close() | 
 | 554 |  | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 555 |     def test_readinto_chunked(self): | 
 | 556 |         chunked_start = ( | 
 | 557 |             'HTTP/1.1 200 OK\r\n' | 
 | 558 |             'Transfer-Encoding: chunked\r\n\r\n' | 
 | 559 |             'a\r\n' | 
 | 560 |             'hello worl\r\n' | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 561 |             '3\r\n' | 
 | 562 |             'd! \r\n' | 
 | 563 |             '8\r\n' | 
 | 564 |             'and now \r\n' | 
 | 565 |             '22\r\n' | 
 | 566 |             'for something completely different\r\n' | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 567 |         ) | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 568 |         expected = b'hello world! and now for something completely different' | 
 | 569 |         nexpected = len(expected) | 
 | 570 |         b = bytearray(128) | 
 | 571 |  | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 572 |         sock = FakeSocket(chunked_start + '0\r\n') | 
 | 573 |         resp = client.HTTPResponse(sock, method="GET") | 
 | 574 |         resp.begin() | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 575 |         n = resp.readinto(b) | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 576 |         self.assertEqual(b[:nexpected], expected) | 
 | 577 |         self.assertEqual(n, nexpected) | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 578 |         resp.close() | 
 | 579 |  | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 580 |         # Various read sizes | 
 | 581 |         for n in range(1, 12): | 
 | 582 |             sock = FakeSocket(chunked_start + '0\r\n') | 
 | 583 |             resp = client.HTTPResponse(sock, method="GET") | 
 | 584 |             resp.begin() | 
 | 585 |             m = memoryview(b) | 
 | 586 |             i = resp.readinto(m[0:n]) | 
 | 587 |             i += resp.readinto(m[i:n + i]) | 
 | 588 |             i += resp.readinto(m[i:]) | 
 | 589 |             self.assertEqual(b[:nexpected], expected) | 
 | 590 |             self.assertEqual(i, nexpected) | 
 | 591 |             resp.close() | 
 | 592 |  | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 593 |         for x in ('', 'foo\r\n'): | 
 | 594 |             sock = FakeSocket(chunked_start + x) | 
 | 595 |             resp = client.HTTPResponse(sock, method="GET") | 
 | 596 |             resp.begin() | 
 | 597 |             try: | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 598 |                 n = resp.readinto(b) | 
 | 599 |             except client.IncompleteRead as i: | 
| Antoine Pitrou | f7e7818 | 2012-01-04 18:57:22 +0100 | [diff] [blame] | 600 |                 self.assertEqual(i.partial, expected) | 
 | 601 |                 expected_message = 'IncompleteRead(%d bytes read)' % len(expected) | 
 | 602 |                 self.assertEqual(repr(i), expected_message) | 
 | 603 |                 self.assertEqual(str(i), expected_message) | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 604 |             else: | 
 | 605 |                 self.fail('IncompleteRead expected') | 
 | 606 |             finally: | 
 | 607 |                 resp.close() | 
 | 608 |  | 
| Senthil Kumaran | 71fb6c8 | 2010-04-28 17:39:48 +0000 | [diff] [blame] | 609 |     def test_chunked_head(self): | 
 | 610 |         chunked_start = ( | 
 | 611 |             'HTTP/1.1 200 OK\r\n' | 
 | 612 |             'Transfer-Encoding: chunked\r\n\r\n' | 
 | 613 |             'a\r\n' | 
 | 614 |             'hello world\r\n' | 
 | 615 |             '1\r\n' | 
 | 616 |             'd\r\n' | 
 | 617 |         ) | 
 | 618 |         sock = FakeSocket(chunked_start + '0\r\n') | 
 | 619 |         resp = client.HTTPResponse(sock, method="HEAD") | 
 | 620 |         resp.begin() | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 621 |         self.assertEqual(resp.read(), b'') | 
 | 622 |         self.assertEqual(resp.status, 200) | 
 | 623 |         self.assertEqual(resp.reason, 'OK') | 
| Senthil Kumaran | 0b99883 | 2010-06-04 17:27:11 +0000 | [diff] [blame] | 624 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b5b9c8c | 2013-02-06 10:31:57 +0200 | [diff] [blame] | 625 |         self.assertFalse(resp.closed) | 
 | 626 |         resp.close() | 
 | 627 |         self.assertTrue(resp.closed) | 
| Senthil Kumaran | 71fb6c8 | 2010-04-28 17:39:48 +0000 | [diff] [blame] | 628 |  | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 629 |     def test_readinto_chunked_head(self): | 
 | 630 |         chunked_start = ( | 
 | 631 |             'HTTP/1.1 200 OK\r\n' | 
 | 632 |             'Transfer-Encoding: chunked\r\n\r\n' | 
 | 633 |             'a\r\n' | 
 | 634 |             'hello world\r\n' | 
 | 635 |             '1\r\n' | 
 | 636 |             'd\r\n' | 
 | 637 |         ) | 
 | 638 |         sock = FakeSocket(chunked_start + '0\r\n') | 
 | 639 |         resp = client.HTTPResponse(sock, method="HEAD") | 
 | 640 |         resp.begin() | 
 | 641 |         b = bytearray(5) | 
 | 642 |         n = resp.readinto(b) | 
 | 643 |         self.assertEqual(n, 0) | 
 | 644 |         self.assertEqual(bytes(b), b'\x00'*5) | 
 | 645 |         self.assertEqual(resp.status, 200) | 
 | 646 |         self.assertEqual(resp.reason, 'OK') | 
 | 647 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b6c86fd | 2013-02-06 10:35:40 +0200 | [diff] [blame] | 648 |         self.assertFalse(resp.closed) | 
 | 649 |         resp.close() | 
 | 650 |         self.assertTrue(resp.closed) | 
| Antoine Pitrou | 38d9643 | 2011-12-06 22:33:57 +0100 | [diff] [blame] | 651 |  | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 652 |     def test_negative_content_length(self): | 
| Jeremy Hylton | 8206695 | 2008-12-15 03:08:30 +0000 | [diff] [blame] | 653 |         sock = FakeSocket( | 
 | 654 |             'HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n') | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 655 |         resp = client.HTTPResponse(sock, method="GET") | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 656 |         resp.begin() | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 657 |         self.assertEqual(resp.read(), b'Hello\r\n') | 
| Antoine Pitrou | beec61a | 2013-02-02 22:49:34 +0100 | [diff] [blame] | 658 |         self.assertTrue(resp.isclosed()) | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 659 |  | 
| Benjamin Peterson | 6accb98 | 2009-03-02 22:50:25 +0000 | [diff] [blame] | 660 |     def test_incomplete_read(self): | 
 | 661 |         sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n') | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 662 |         resp = client.HTTPResponse(sock, method="GET") | 
| Benjamin Peterson | 6accb98 | 2009-03-02 22:50:25 +0000 | [diff] [blame] | 663 |         resp.begin() | 
 | 664 |         try: | 
 | 665 |             resp.read() | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 666 |         except client.IncompleteRead as i: | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 667 |             self.assertEqual(i.partial, b'Hello\r\n') | 
| Benjamin Peterson | 6accb98 | 2009-03-02 22:50:25 +0000 | [diff] [blame] | 668 |             self.assertEqual(repr(i), | 
 | 669 |                              "IncompleteRead(7 bytes read, 3 more expected)") | 
 | 670 |             self.assertEqual(str(i), | 
 | 671 |                              "IncompleteRead(7 bytes read, 3 more expected)") | 
| Antoine Pitrou | beec61a | 2013-02-02 22:49:34 +0100 | [diff] [blame] | 672 |             self.assertTrue(resp.isclosed()) | 
| Benjamin Peterson | 6accb98 | 2009-03-02 22:50:25 +0000 | [diff] [blame] | 673 |         else: | 
 | 674 |             self.fail('IncompleteRead expected') | 
| Benjamin Peterson | 6accb98 | 2009-03-02 22:50:25 +0000 | [diff] [blame] | 675 |  | 
| Jeremy Hylton | 636950f | 2009-03-28 04:34:21 +0000 | [diff] [blame] | 676 |     def test_epipe(self): | 
 | 677 |         sock = EPipeSocket( | 
 | 678 |             "HTTP/1.0 401 Authorization Required\r\n" | 
 | 679 |             "Content-type: text/html\r\n" | 
 | 680 |             "WWW-Authenticate: Basic realm=\"example\"\r\n", | 
 | 681 |             b"Content-Length") | 
 | 682 |         conn = client.HTTPConnection("example.com") | 
 | 683 |         conn.sock = sock | 
| Andrew Svetlov | 0832af6 | 2012-12-18 23:10:48 +0200 | [diff] [blame] | 684 |         self.assertRaises(OSError, | 
| Jeremy Hylton | 636950f | 2009-03-28 04:34:21 +0000 | [diff] [blame] | 685 |                           lambda: conn.request("PUT", "/url", "body")) | 
 | 686 |         resp = conn.getresponse() | 
 | 687 |         self.assertEqual(401, resp.status) | 
 | 688 |         self.assertEqual("Basic realm=\"example\"", | 
 | 689 |                          resp.getheader("www-authenticate")) | 
| Christian Heimes | a612dc0 | 2008-02-24 13:08:18 +0000 | [diff] [blame] | 690 |  | 
| Senthil Kumaran | 5466bf1 | 2010-12-18 16:55:23 +0000 | [diff] [blame] | 691 |     # Test lines overflowing the max line size (_MAXLINE in http.client) | 
 | 692 |  | 
 | 693 |     def test_overflowing_status_line(self): | 
 | 694 |         body = "HTTP/1.1 200 Ok" + "k" * 65536 + "\r\n" | 
 | 695 |         resp = client.HTTPResponse(FakeSocket(body)) | 
 | 696 |         self.assertRaises((client.LineTooLong, client.BadStatusLine), resp.begin) | 
 | 697 |  | 
 | 698 |     def test_overflowing_header_line(self): | 
 | 699 |         body = ( | 
 | 700 |             'HTTP/1.1 200 OK\r\n' | 
 | 701 |             'X-Foo: bar' + 'r' * 65536 + '\r\n\r\n' | 
 | 702 |         ) | 
 | 703 |         resp = client.HTTPResponse(FakeSocket(body)) | 
 | 704 |         self.assertRaises(client.LineTooLong, resp.begin) | 
 | 705 |  | 
 | 706 |     def test_overflowing_chunked_line(self): | 
 | 707 |         body = ( | 
 | 708 |             'HTTP/1.1 200 OK\r\n' | 
 | 709 |             'Transfer-Encoding: chunked\r\n\r\n' | 
 | 710 |             + '0' * 65536 + 'a\r\n' | 
 | 711 |             'hello world\r\n' | 
 | 712 |             '0\r\n' | 
 | 713 |         ) | 
 | 714 |         resp = client.HTTPResponse(FakeSocket(body)) | 
 | 715 |         resp.begin() | 
 | 716 |         self.assertRaises(client.LineTooLong, resp.read) | 
 | 717 |  | 
| Senthil Kumaran | 9c29f86 | 2012-04-29 10:20:46 +0800 | [diff] [blame] | 718 |     def test_early_eof(self): | 
 | 719 |         # Test httpresponse with no \r\n termination, | 
 | 720 |         body = "HTTP/1.1 200 Ok" | 
 | 721 |         sock = FakeSocket(body) | 
 | 722 |         resp = client.HTTPResponse(sock) | 
 | 723 |         resp.begin() | 
 | 724 |         self.assertEqual(resp.read(), b'') | 
 | 725 |         self.assertTrue(resp.isclosed()) | 
| Serhiy Storchaka | b5b9c8c | 2013-02-06 10:31:57 +0200 | [diff] [blame] | 726 |         self.assertFalse(resp.closed) | 
 | 727 |         resp.close() | 
 | 728 |         self.assertTrue(resp.closed) | 
| Senthil Kumaran | 9c29f86 | 2012-04-29 10:20:46 +0800 | [diff] [blame] | 729 |  | 
| Antoine Pitrou | 90e4774 | 2013-01-02 22:10:47 +0100 | [diff] [blame] | 730 |     def test_delayed_ack_opt(self): | 
 | 731 |         # Test that Nagle/delayed_ack optimistaion works correctly. | 
 | 732 |  | 
 | 733 |         # For small payloads, it should coalesce the body with | 
 | 734 |         # headers, resulting in a single sendall() call | 
 | 735 |         conn = client.HTTPConnection('example.com') | 
 | 736 |         sock = FakeSocket(None) | 
 | 737 |         conn.sock = sock | 
 | 738 |         body = b'x' * (conn.mss - 1) | 
 | 739 |         conn.request('POST', '/', body) | 
 | 740 |         self.assertEqual(sock.sendall_calls, 1) | 
 | 741 |  | 
 | 742 |         # For large payloads, it should send the headers and | 
 | 743 |         # then the body, resulting in more than one sendall() | 
 | 744 |         # call | 
 | 745 |         conn = client.HTTPConnection('example.com') | 
 | 746 |         sock = FakeSocket(None) | 
 | 747 |         conn.sock = sock | 
 | 748 |         body = b'x' * conn.mss | 
 | 749 |         conn.request('POST', '/', body) | 
 | 750 |         self.assertGreater(sock.sendall_calls, 1) | 
 | 751 |  | 
| Serhiy Storchaka | b491e05 | 2014-12-01 13:07:45 +0200 | [diff] [blame] | 752 |     def test_error_leak(self): | 
 | 753 |         # Test that the socket is not leaked if getresponse() fails | 
 | 754 |         conn = client.HTTPConnection('example.com') | 
 | 755 |         response = None | 
 | 756 |         class Response(client.HTTPResponse): | 
 | 757 |             def __init__(self, *pos, **kw): | 
 | 758 |                 nonlocal response | 
 | 759 |                 response = self  # Avoid garbage collector closing the socket | 
 | 760 |                 client.HTTPResponse.__init__(self, *pos, **kw) | 
 | 761 |         conn.response_class = Response | 
 | 762 |         conn.sock = FakeSocket('')  # Emulate server dropping connection | 
 | 763 |         conn.request('GET', '/') | 
 | 764 |         self.assertRaises(client.BadStatusLine, conn.getresponse) | 
 | 765 |         self.assertTrue(response.closed) | 
 | 766 |         self.assertTrue(conn.sock.file_closed) | 
 | 767 |  | 
| Berker Peksag | babc688 | 2015-02-20 09:39:38 +0200 | [diff] [blame] | 768 |  | 
| Georg Brandl | 4cbd1e3 | 2006-02-17 22:01:08 +0000 | [diff] [blame] | 769 | class OfflineTest(TestCase): | 
| Berker Peksag | babc688 | 2015-02-20 09:39:38 +0200 | [diff] [blame] | 770 |     def test_all(self): | 
 | 771 |         # Documented objects defined in the module should be in __all__ | 
 | 772 |         expected = {"responses"}  # White-list documented dict() object | 
 | 773 |         # HTTPMessage, parse_headers(), and the HTTP status code constants are | 
 | 774 |         # intentionally omitted for simplicity | 
 | 775 |         blacklist = {"HTTPMessage", "parse_headers"} | 
 | 776 |         for name in dir(client): | 
 | 777 |             if name in blacklist: | 
 | 778 |                 continue | 
 | 779 |             module_object = getattr(client, name) | 
 | 780 |             if getattr(module_object, "__module__", None) == "http.client": | 
 | 781 |                 expected.add(name) | 
 | 782 |         self.assertCountEqual(client.__all__, expected) | 
 | 783 |  | 
| Georg Brandl | 4cbd1e3 | 2006-02-17 22:01:08 +0000 | [diff] [blame] | 784 |     def test_responses(self): | 
| Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame] | 785 |         self.assertEqual(client.responses[client.NOT_FOUND], "Not Found") | 
| Georg Brandl | 4cbd1e3 | 2006-02-17 22:01:08 +0000 | [diff] [blame] | 786 |  | 
| Gregory P. Smith | b406637 | 2010-01-03 03:28:29 +0000 | [diff] [blame] | 787 |  | 
 | 788 | class SourceAddressTest(TestCase): | 
 | 789 |     def setUp(self): | 
 | 790 |         self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
 | 791 |         self.port = support.bind_port(self.serv) | 
 | 792 |         self.source_port = support.find_unused_port() | 
 | 793 |         self.serv.listen(5) | 
 | 794 |         self.conn = None | 
 | 795 |  | 
 | 796 |     def tearDown(self): | 
 | 797 |         if self.conn: | 
 | 798 |             self.conn.close() | 
 | 799 |             self.conn = None | 
 | 800 |         self.serv.close() | 
 | 801 |         self.serv = None | 
 | 802 |  | 
 | 803 |     def testHTTPConnectionSourceAddress(self): | 
 | 804 |         self.conn = client.HTTPConnection(HOST, self.port, | 
 | 805 |                 source_address=('', self.source_port)) | 
 | 806 |         self.conn.connect() | 
 | 807 |         self.assertEqual(self.conn.sock.getsockname()[1], self.source_port) | 
 | 808 |  | 
 | 809 |     @unittest.skipIf(not hasattr(client, 'HTTPSConnection'), | 
 | 810 |                      'http.client.HTTPSConnection not defined') | 
 | 811 |     def testHTTPSConnectionSourceAddress(self): | 
 | 812 |         self.conn = client.HTTPSConnection(HOST, self.port, | 
 | 813 |                 source_address=('', self.source_port)) | 
 | 814 |         # We don't test anything here other the constructor not barfing as | 
 | 815 |         # this code doesn't deal with setting up an active running SSL server | 
 | 816 |         # for an ssl_wrapped connect() to actually return from. | 
 | 817 |  | 
 | 818 |  | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 819 | class TimeoutTest(TestCase): | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 820 |     PORT = None | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 821 |  | 
 | 822 |     def setUp(self): | 
 | 823 |         self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
| Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 824 |         TimeoutTest.PORT = support.bind_port(self.serv) | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 825 |         self.serv.listen(5) | 
 | 826 |  | 
 | 827 |     def tearDown(self): | 
 | 828 |         self.serv.close() | 
 | 829 |         self.serv = None | 
 | 830 |  | 
 | 831 |     def testTimeoutAttribute(self): | 
| Jeremy Hylton | 3a38c91 | 2007-08-14 17:08:07 +0000 | [diff] [blame] | 832 |         # This will prove that the timeout gets through HTTPConnection | 
 | 833 |         # and into the socket. | 
 | 834 |  | 
| Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 835 |         # default -- use global socket timeout | 
| Serhiy Storchaka | 25d8aea | 2014-02-08 14:50:08 +0200 | [diff] [blame] | 836 |         self.assertIsNone(socket.getdefaulttimeout()) | 
| Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 837 |         socket.setdefaulttimeout(30) | 
 | 838 |         try: | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 839 |             httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT) | 
| Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 840 |             httpConn.connect() | 
 | 841 |         finally: | 
 | 842 |             socket.setdefaulttimeout(None) | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 843 |         self.assertEqual(httpConn.sock.gettimeout(), 30) | 
 | 844 |         httpConn.close() | 
 | 845 |  | 
| Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 846 |         # no timeout -- do not use global socket default | 
| Serhiy Storchaka | 25d8aea | 2014-02-08 14:50:08 +0200 | [diff] [blame] | 847 |         self.assertIsNone(socket.getdefaulttimeout()) | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 848 |         socket.setdefaulttimeout(30) | 
 | 849 |         try: | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 850 |             httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT, | 
| Christian Heimes | 5e69685 | 2008-04-09 08:37:03 +0000 | [diff] [blame] | 851 |                                               timeout=None) | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 852 |             httpConn.connect() | 
 | 853 |         finally: | 
| Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 854 |             socket.setdefaulttimeout(None) | 
 | 855 |         self.assertEqual(httpConn.sock.gettimeout(), None) | 
 | 856 |         httpConn.close() | 
 | 857 |  | 
 | 858 |         # a value | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 859 |         httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30) | 
| Georg Brandl | f78e02b | 2008-06-10 17:40:04 +0000 | [diff] [blame] | 860 |         httpConn.connect() | 
| Guido van Rossum | d8faa36 | 2007-04-27 19:54:29 +0000 | [diff] [blame] | 861 |         self.assertEqual(httpConn.sock.gettimeout(), 30) | 
 | 862 |         httpConn.close() | 
 | 863 |  | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 864 |  | 
 | 865 | class HTTPSTest(TestCase): | 
 | 866 |  | 
 | 867 |     def setUp(self): | 
 | 868 |         if not hasattr(client, 'HTTPSConnection'): | 
 | 869 |             self.skipTest('ssl support required') | 
 | 870 |  | 
 | 871 |     def make_server(self, certfile): | 
 | 872 |         from test.ssl_servers import make_https_server | 
| Antoine Pitrou | da23259 | 2013-02-05 21:20:51 +0100 | [diff] [blame] | 873 |         return make_https_server(self, certfile=certfile) | 
| Guido van Rossum | d59da4b | 2007-05-22 18:11:13 +0000 | [diff] [blame] | 874 |  | 
 | 875 |     def test_attributes(self): | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 876 |         # simple test to check it's storing the timeout | 
 | 877 |         h = client.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) | 
 | 878 |         self.assertEqual(h.timeout, 30) | 
 | 879 |  | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 880 |     def test_networked(self): | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 881 |         # Default settings: requires a valid cert from a trusted CA | 
 | 882 |         import ssl | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 883 |         support.requires('network') | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 884 |         with support.transient_internet('self-signed.pythontest.net'): | 
 | 885 |             h = client.HTTPSConnection('self-signed.pythontest.net', 443) | 
 | 886 |             with self.assertRaises(ssl.SSLError) as exc_info: | 
 | 887 |                 h.request('GET', '/') | 
 | 888 |             self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') | 
 | 889 |  | 
 | 890 |     def test_networked_noverification(self): | 
 | 891 |         # Switch off cert verification | 
 | 892 |         import ssl | 
 | 893 |         support.requires('network') | 
 | 894 |         with support.transient_internet('self-signed.pythontest.net'): | 
 | 895 |             context = ssl._create_unverified_context() | 
 | 896 |             h = client.HTTPSConnection('self-signed.pythontest.net', 443, | 
 | 897 |                                        context=context) | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 898 |             h.request('GET', '/') | 
 | 899 |             resp = h.getresponse() | 
| Victor Stinner | b389b48 | 2015-02-27 17:47:23 +0100 | [diff] [blame] | 900 |             h.close() | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 901 |             self.assertIn('nginx', resp.getheader('server')) | 
 | 902 |  | 
| Benjamin Peterson | 2615e9e | 2014-11-25 15:16:55 -0600 | [diff] [blame] | 903 |     @support.system_must_validate_cert | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 904 |     def test_networked_trusted_by_default_cert(self): | 
 | 905 |         # Default settings: requires a valid cert from a trusted CA | 
 | 906 |         support.requires('network') | 
 | 907 |         with support.transient_internet('www.python.org'): | 
 | 908 |             h = client.HTTPSConnection('www.python.org', 443) | 
 | 909 |             h.request('GET', '/') | 
 | 910 |             resp = h.getresponse() | 
 | 911 |             content_type = resp.getheader('content-type') | 
| Victor Stinner | b389b48 | 2015-02-27 17:47:23 +0100 | [diff] [blame] | 912 |             h.close() | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 913 |             self.assertIn('text/html', content_type) | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 914 |  | 
 | 915 |     def test_networked_good_cert(self): | 
| Georg Brandl | fbaf931 | 2014-11-05 20:37:40 +0100 | [diff] [blame] | 916 |         # We feed the server's cert as a validating cert | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 917 |         import ssl | 
 | 918 |         support.requires('network') | 
| Georg Brandl | fbaf931 | 2014-11-05 20:37:40 +0100 | [diff] [blame] | 919 |         with support.transient_internet('self-signed.pythontest.net'): | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 920 |             context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | 
 | 921 |             context.verify_mode = ssl.CERT_REQUIRED | 
| Georg Brandl | fbaf931 | 2014-11-05 20:37:40 +0100 | [diff] [blame] | 922 |             context.load_verify_locations(CERT_selfsigned_pythontestdotnet) | 
 | 923 |             h = client.HTTPSConnection('self-signed.pythontest.net', 443, context=context) | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 924 |             h.request('GET', '/') | 
 | 925 |             resp = h.getresponse() | 
| Georg Brandl | fbaf931 | 2014-11-05 20:37:40 +0100 | [diff] [blame] | 926 |             server_string = resp.getheader('server') | 
| Victor Stinner | b389b48 | 2015-02-27 17:47:23 +0100 | [diff] [blame] | 927 |             h.close() | 
| Georg Brandl | fbaf931 | 2014-11-05 20:37:40 +0100 | [diff] [blame] | 928 |             self.assertIn('nginx', server_string) | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 929 |  | 
 | 930 |     def test_networked_bad_cert(self): | 
 | 931 |         # We feed a "CA" cert that is unrelated to the server's cert | 
 | 932 |         import ssl | 
 | 933 |         support.requires('network') | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 934 |         with support.transient_internet('self-signed.pythontest.net'): | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 935 |             context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | 
 | 936 |             context.verify_mode = ssl.CERT_REQUIRED | 
 | 937 |             context.load_verify_locations(CERT_localhost) | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 938 |             h = client.HTTPSConnection('self-signed.pythontest.net', 443, context=context) | 
 | 939 |             with self.assertRaises(ssl.SSLError) as exc_info: | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 940 |                 h.request('GET', '/') | 
| Benjamin Peterson | 4ffb075 | 2014-11-03 14:29:33 -0500 | [diff] [blame] | 941 |             self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') | 
 | 942 |  | 
 | 943 |     def test_local_unknown_cert(self): | 
 | 944 |         # The custom cert isn't known to the default trust bundle | 
 | 945 |         import ssl | 
 | 946 |         server = self.make_server(CERT_localhost) | 
 | 947 |         h = client.HTTPSConnection('localhost', server.port) | 
 | 948 |         with self.assertRaises(ssl.SSLError) as exc_info: | 
 | 949 |             h.request('GET', '/') | 
 | 950 |         self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 951 |  | 
 | 952 |     def test_local_good_hostname(self): | 
 | 953 |         # The (valid) cert validates the HTTP hostname | 
 | 954 |         import ssl | 
| Brett Cannon | 252365b | 2011-08-04 22:43:11 -0700 | [diff] [blame] | 955 |         server = self.make_server(CERT_localhost) | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 956 |         context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | 
 | 957 |         context.verify_mode = ssl.CERT_REQUIRED | 
 | 958 |         context.load_verify_locations(CERT_localhost) | 
 | 959 |         h = client.HTTPSConnection('localhost', server.port, context=context) | 
 | 960 |         h.request('GET', '/nonexistent') | 
 | 961 |         resp = h.getresponse() | 
 | 962 |         self.assertEqual(resp.status, 404) | 
 | 963 |  | 
 | 964 |     def test_local_bad_hostname(self): | 
 | 965 |         # The (valid) cert doesn't validate the HTTP hostname | 
 | 966 |         import ssl | 
| Brett Cannon | 252365b | 2011-08-04 22:43:11 -0700 | [diff] [blame] | 967 |         server = self.make_server(CERT_fakehostname) | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 968 |         context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | 
 | 969 |         context.verify_mode = ssl.CERT_REQUIRED | 
| Benjamin Peterson | a090f01 | 2014-12-07 13:18:25 -0500 | [diff] [blame] | 970 |         context.check_hostname = True | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 971 |         context.load_verify_locations(CERT_fakehostname) | 
 | 972 |         h = client.HTTPSConnection('localhost', server.port, context=context) | 
 | 973 |         with self.assertRaises(ssl.CertificateError): | 
 | 974 |             h.request('GET', '/') | 
 | 975 |         # Same with explicit check_hostname=True | 
 | 976 |         h = client.HTTPSConnection('localhost', server.port, context=context, | 
 | 977 |                                    check_hostname=True) | 
 | 978 |         with self.assertRaises(ssl.CertificateError): | 
 | 979 |             h.request('GET', '/') | 
 | 980 |         # With check_hostname=False, the mismatching is ignored | 
| Benjamin Peterson | a090f01 | 2014-12-07 13:18:25 -0500 | [diff] [blame] | 981 |         context.check_hostname = False | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 982 |         h = client.HTTPSConnection('localhost', server.port, context=context, | 
 | 983 |                                    check_hostname=False) | 
 | 984 |         h.request('GET', '/nonexistent') | 
 | 985 |         resp = h.getresponse() | 
 | 986 |         self.assertEqual(resp.status, 404) | 
| Benjamin Peterson | a090f01 | 2014-12-07 13:18:25 -0500 | [diff] [blame] | 987 |         # The context's check_hostname setting is used if one isn't passed to | 
 | 988 |         # HTTPSConnection. | 
 | 989 |         context.check_hostname = False | 
 | 990 |         h = client.HTTPSConnection('localhost', server.port, context=context) | 
 | 991 |         h.request('GET', '/nonexistent') | 
 | 992 |         self.assertEqual(h.getresponse().status, 404) | 
 | 993 |         # Passing check_hostname to HTTPSConnection should override the | 
 | 994 |         # context's setting. | 
 | 995 |         h = client.HTTPSConnection('localhost', server.port, context=context, | 
 | 996 |                                    check_hostname=True) | 
 | 997 |         with self.assertRaises(ssl.CertificateError): | 
 | 998 |             h.request('GET', '/') | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 999 |  | 
| Petri Lehtinen | e119c40 | 2011-10-26 21:29:15 +0300 | [diff] [blame] | 1000 |     @unittest.skipIf(not hasattr(client, 'HTTPSConnection'), | 
 | 1001 |                      'http.client.HTTPSConnection not available') | 
| Łukasz Langa | a5a9a9c | 2011-10-18 21:17:39 +0200 | [diff] [blame] | 1002 |     def test_host_port(self): | 
 | 1003 |         # Check invalid host_port | 
 | 1004 |  | 
 | 1005 |         for hp in ("www.python.org:abc", "user:password@www.python.org"): | 
 | 1006 |             self.assertRaises(client.InvalidURL, client.HTTPSConnection, hp) | 
 | 1007 |  | 
 | 1008 |         for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", | 
 | 1009 |                           "fe80::207:e9ff:fe9b", 8000), | 
 | 1010 |                          ("www.python.org:443", "www.python.org", 443), | 
 | 1011 |                          ("www.python.org:", "www.python.org", 443), | 
 | 1012 |                          ("www.python.org", "www.python.org", 443), | 
 | 1013 |                          ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443), | 
 | 1014 |                          ("[fe80::207:e9ff:fe9b]:", "fe80::207:e9ff:fe9b", | 
 | 1015 |                              443)): | 
 | 1016 |             c = client.HTTPSConnection(hp) | 
 | 1017 |             self.assertEqual(h, c.host) | 
 | 1018 |             self.assertEqual(p, c.port) | 
 | 1019 |  | 
| Guido van Rossum | d59da4b | 2007-05-22 18:11:13 +0000 | [diff] [blame] | 1020 |  | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1021 | class RequestBodyTest(TestCase): | 
 | 1022 |     """Test cases where a request includes a message body.""" | 
 | 1023 |  | 
 | 1024 |     def setUp(self): | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 1025 |         self.conn = client.HTTPConnection('example.com') | 
| Jeremy Hylton | 636950f | 2009-03-28 04:34:21 +0000 | [diff] [blame] | 1026 |         self.conn.sock = self.sock = FakeSocket("") | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1027 |         self.conn.sock = self.sock | 
 | 1028 |  | 
 | 1029 |     def get_headers_and_fp(self): | 
 | 1030 |         f = io.BytesIO(self.sock.data) | 
 | 1031 |         f.readline()  # read the request line | 
| Jeremy Hylton | 7c1692d | 2009-03-27 21:31:03 +0000 | [diff] [blame] | 1032 |         message = client.parse_headers(f) | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1033 |         return message, f | 
 | 1034 |  | 
 | 1035 |     def test_manual_content_length(self): | 
 | 1036 |         # Set an incorrect content-length so that we can verify that | 
 | 1037 |         # it will not be over-ridden by the library. | 
 | 1038 |         self.conn.request("PUT", "/url", "body", | 
 | 1039 |                           {"Content-Length": "42"}) | 
 | 1040 |         message, f = self.get_headers_and_fp() | 
 | 1041 |         self.assertEqual("42", message.get("content-length")) | 
 | 1042 |         self.assertEqual(4, len(f.read())) | 
 | 1043 |  | 
 | 1044 |     def test_ascii_body(self): | 
 | 1045 |         self.conn.request("PUT", "/url", "body") | 
 | 1046 |         message, f = self.get_headers_and_fp() | 
 | 1047 |         self.assertEqual("text/plain", message.get_content_type()) | 
| Raymond Hettinger | 7beae8a | 2011-01-06 05:34:17 +0000 | [diff] [blame] | 1048 |         self.assertIsNone(message.get_charset()) | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1049 |         self.assertEqual("4", message.get("content-length")) | 
 | 1050 |         self.assertEqual(b'body', f.read()) | 
 | 1051 |  | 
 | 1052 |     def test_latin1_body(self): | 
 | 1053 |         self.conn.request("PUT", "/url", "body\xc1") | 
 | 1054 |         message, f = self.get_headers_and_fp() | 
 | 1055 |         self.assertEqual("text/plain", message.get_content_type()) | 
| Raymond Hettinger | 7beae8a | 2011-01-06 05:34:17 +0000 | [diff] [blame] | 1056 |         self.assertIsNone(message.get_charset()) | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1057 |         self.assertEqual("5", message.get("content-length")) | 
 | 1058 |         self.assertEqual(b'body\xc1', f.read()) | 
 | 1059 |  | 
 | 1060 |     def test_bytes_body(self): | 
 | 1061 |         self.conn.request("PUT", "/url", b"body\xc1") | 
 | 1062 |         message, f = self.get_headers_and_fp() | 
 | 1063 |         self.assertEqual("text/plain", message.get_content_type()) | 
| Raymond Hettinger | 7beae8a | 2011-01-06 05:34:17 +0000 | [diff] [blame] | 1064 |         self.assertIsNone(message.get_charset()) | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1065 |         self.assertEqual("5", message.get("content-length")) | 
 | 1066 |         self.assertEqual(b'body\xc1', f.read()) | 
 | 1067 |  | 
 | 1068 |     def test_file_body(self): | 
| Victor Stinner | 18d15cb | 2011-09-21 01:09:04 +0200 | [diff] [blame] | 1069 |         self.addCleanup(support.unlink, support.TESTFN) | 
| Brett Cannon | 77b7de6 | 2010-10-29 23:31:11 +0000 | [diff] [blame] | 1070 |         with open(support.TESTFN, "w") as f: | 
 | 1071 |             f.write("body") | 
 | 1072 |         with open(support.TESTFN) as f: | 
 | 1073 |             self.conn.request("PUT", "/url", f) | 
 | 1074 |             message, f = self.get_headers_and_fp() | 
 | 1075 |             self.assertEqual("text/plain", message.get_content_type()) | 
| Raymond Hettinger | 7beae8a | 2011-01-06 05:34:17 +0000 | [diff] [blame] | 1076 |             self.assertIsNone(message.get_charset()) | 
| Brett Cannon | 77b7de6 | 2010-10-29 23:31:11 +0000 | [diff] [blame] | 1077 |             self.assertEqual("4", message.get("content-length")) | 
 | 1078 |             self.assertEqual(b'body', f.read()) | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1079 |  | 
 | 1080 |     def test_binary_file_body(self): | 
| Victor Stinner | 18d15cb | 2011-09-21 01:09:04 +0200 | [diff] [blame] | 1081 |         self.addCleanup(support.unlink, support.TESTFN) | 
| Brett Cannon | 77b7de6 | 2010-10-29 23:31:11 +0000 | [diff] [blame] | 1082 |         with open(support.TESTFN, "wb") as f: | 
 | 1083 |             f.write(b"body\xc1") | 
 | 1084 |         with open(support.TESTFN, "rb") as f: | 
 | 1085 |             self.conn.request("PUT", "/url", f) | 
 | 1086 |             message, f = self.get_headers_and_fp() | 
 | 1087 |             self.assertEqual("text/plain", message.get_content_type()) | 
| Raymond Hettinger | 7beae8a | 2011-01-06 05:34:17 +0000 | [diff] [blame] | 1088 |             self.assertIsNone(message.get_charset()) | 
| Brett Cannon | 77b7de6 | 2010-10-29 23:31:11 +0000 | [diff] [blame] | 1089 |             self.assertEqual("5", message.get("content-length")) | 
 | 1090 |             self.assertEqual(b'body\xc1', f.read()) | 
| Jeremy Hylton | 236654b | 2009-03-27 20:24:34 +0000 | [diff] [blame] | 1091 |  | 
| Senthil Kumaran | 9f8dc44 | 2010-08-02 11:04:58 +0000 | [diff] [blame] | 1092 |  | 
 | 1093 | class HTTPResponseTest(TestCase): | 
 | 1094 |  | 
 | 1095 |     def setUp(self): | 
 | 1096 |         body = "HTTP/1.1 200 Ok\r\nMy-Header: first-value\r\nMy-Header: \ | 
 | 1097 |                 second-value\r\n\r\nText" | 
 | 1098 |         sock = FakeSocket(body) | 
 | 1099 |         self.resp = client.HTTPResponse(sock) | 
 | 1100 |         self.resp.begin() | 
 | 1101 |  | 
 | 1102 |     def test_getting_header(self): | 
 | 1103 |         header = self.resp.getheader('My-Header') | 
 | 1104 |         self.assertEqual(header, 'first-value, second-value') | 
 | 1105 |  | 
 | 1106 |         header = self.resp.getheader('My-Header', 'some default') | 
 | 1107 |         self.assertEqual(header, 'first-value, second-value') | 
 | 1108 |  | 
 | 1109 |     def test_getting_nonexistent_header_with_string_default(self): | 
 | 1110 |         header = self.resp.getheader('No-Such-Header', 'default-value') | 
 | 1111 |         self.assertEqual(header, 'default-value') | 
 | 1112 |  | 
 | 1113 |     def test_getting_nonexistent_header_with_iterable_default(self): | 
 | 1114 |         header = self.resp.getheader('No-Such-Header', ['default', 'values']) | 
 | 1115 |         self.assertEqual(header, 'default, values') | 
 | 1116 |  | 
 | 1117 |         header = self.resp.getheader('No-Such-Header', ('default', 'values')) | 
 | 1118 |         self.assertEqual(header, 'default, values') | 
 | 1119 |  | 
 | 1120 |     def test_getting_nonexistent_header_without_default(self): | 
 | 1121 |         header = self.resp.getheader('No-Such-Header') | 
 | 1122 |         self.assertEqual(header, None) | 
 | 1123 |  | 
 | 1124 |     def test_getting_header_defaultint(self): | 
 | 1125 |         header = self.resp.getheader('No-Such-Header',default=42) | 
 | 1126 |         self.assertEqual(header, 42) | 
 | 1127 |  | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1128 | class TunnelTests(TestCase): | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1129 |     def setUp(self): | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1130 |         response_text = ( | 
 | 1131 |             'HTTP/1.0 200 OK\r\n\r\n' # Reply to CONNECT | 
 | 1132 |             'HTTP/1.1 200 OK\r\n' # Reply to HEAD | 
 | 1133 |             'Content-Length: 42\r\n\r\n' | 
 | 1134 |         ) | 
 | 1135 |  | 
 | 1136 |         def create_connection(address, timeout=None, source_address=None): | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1137 |             return FakeSocket(response_text, host=address[0], port=address[1]) | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1138 |  | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1139 |         self.host = 'proxy.com' | 
 | 1140 |         self.conn = client.HTTPConnection(self.host) | 
 | 1141 |         self.conn._create_connection = create_connection | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1142 |  | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1143 |     def tearDown(self): | 
 | 1144 |         self.conn.close() | 
 | 1145 |  | 
 | 1146 |     def test_set_tunnel_host_port_headers(self): | 
 | 1147 |         tunnel_host = 'destination.com' | 
 | 1148 |         tunnel_port = 8888 | 
 | 1149 |         tunnel_headers = {'User-Agent': 'Mozilla/5.0 (compatible, MSIE 11)'} | 
 | 1150 |         self.conn.set_tunnel(tunnel_host, port=tunnel_port, | 
 | 1151 |                              headers=tunnel_headers) | 
 | 1152 |         self.conn.request('HEAD', '/', '') | 
 | 1153 |         self.assertEqual(self.conn.sock.host, self.host) | 
 | 1154 |         self.assertEqual(self.conn.sock.port, client.HTTP_PORT) | 
 | 1155 |         self.assertEqual(self.conn._tunnel_host, tunnel_host) | 
 | 1156 |         self.assertEqual(self.conn._tunnel_port, tunnel_port) | 
 | 1157 |         self.assertEqual(self.conn._tunnel_headers, tunnel_headers) | 
 | 1158 |  | 
 | 1159 |     def test_disallow_set_tunnel_after_connect(self): | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1160 |         # Once connected, we shouldn't be able to tunnel anymore | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1161 |         self.conn.connect() | 
 | 1162 |         self.assertRaises(RuntimeError, self.conn.set_tunnel, | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1163 |                           'destination.com') | 
 | 1164 |  | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1165 |     def test_connect_with_tunnel(self): | 
 | 1166 |         self.conn.set_tunnel('destination.com') | 
 | 1167 |         self.conn.request('HEAD', '/', '') | 
 | 1168 |         self.assertEqual(self.conn.sock.host, self.host) | 
 | 1169 |         self.assertEqual(self.conn.sock.port, client.HTTP_PORT) | 
 | 1170 |         self.assertIn(b'CONNECT destination.com', self.conn.sock.data) | 
| Serhiy Storchaka | 4ac7ed9 | 2014-12-12 09:29:15 +0200 | [diff] [blame] | 1171 |         # issue22095 | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1172 |         self.assertNotIn(b'Host: destination.com:None', self.conn.sock.data) | 
 | 1173 |         self.assertIn(b'Host: destination.com', self.conn.sock.data) | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1174 |  | 
 | 1175 |         # This test should be removed when CONNECT gets the HTTP/1.1 blessing | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1176 |         self.assertNotIn(b'Host: proxy.com', self.conn.sock.data) | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1177 |  | 
| Senthil Kumaran | e6cc701 | 2015-01-24 19:24:59 -0800 | [diff] [blame] | 1178 |     def test_connect_put_request(self): | 
 | 1179 |         self.conn.set_tunnel('destination.com') | 
 | 1180 |         self.conn.request('PUT', '/', '') | 
 | 1181 |         self.assertEqual(self.conn.sock.host, self.host) | 
 | 1182 |         self.assertEqual(self.conn.sock.port, client.HTTP_PORT) | 
 | 1183 |         self.assertIn(b'CONNECT destination.com', self.conn.sock.data) | 
 | 1184 |         self.assertIn(b'Host: destination.com', self.conn.sock.data) | 
 | 1185 |  | 
 | 1186 |  | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1187 |  | 
| Benjamin Peterson | 9566de1 | 2014-12-13 16:13:24 -0500 | [diff] [blame] | 1188 | @support.reap_threads | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 1189 | def test_main(verbose=None): | 
| Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 1190 |     support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, | 
| Antoine Pitrou | 803e6d6 | 2010-10-13 10:36:15 +0000 | [diff] [blame] | 1191 |                          HTTPSTest, RequestBodyTest, SourceAddressTest, | 
| Senthil Kumaran | 9da047b | 2014-04-14 13:07:56 -0400 | [diff] [blame] | 1192 |                          HTTPResponseTest, TunnelTests) | 
| Jeremy Hylton | 2c17825 | 2004-08-07 16:28:14 +0000 | [diff] [blame] | 1193 |  | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 1194 | if __name__ == '__main__': | 
 | 1195 |     test_main() |