blob: a433474bc0e50a19660d976f40583cee1f2cdbff [file] [log] [blame]
Georg Brandl24420152008-05-26 16:32:26 +00001import http.client as httplib
Jeremy Hylton8fff7922007-08-03 20:56:14 +00002import io
Guido van Rossumd8faa362007-04-27 19:54:29 +00003import socket
Jeremy Hylton121d34a2003-07-08 12:36:58 +00004
Jeremy Hylton2c178252004-08-07 16:28:14 +00005from unittest import TestCase
6
Benjamin Petersonee8712c2008-05-20 21:35:26 +00007from test import support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00008
Benjamin Petersonee8712c2008-05-20 21:35:26 +00009HOST = support.HOST
Christian Heimes5e696852008-04-09 08:37:03 +000010
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000011class FakeSocket:
Jeremy Hylton8fff7922007-08-03 20:56:14 +000012 def __init__(self, text, fileclass=io.BytesIO):
13 if isinstance(text, str):
Guido van Rossum39478e82007-08-27 17:23:59 +000014 text = text.encode("ascii")
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000015 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000016 self.fileclass = fileclass
Martin v. Löwisdd5a8602007-06-30 09:22:09 +000017 self.data = b''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000018
Jeremy Hylton2c178252004-08-07 16:28:14 +000019 def sendall(self, data):
Thomas Wouters89f507f2006-12-13 04:49:30 +000020 self.data += data
Jeremy Hylton2c178252004-08-07 16:28:14 +000021
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000022 def makefile(self, mode, bufsize=None):
23 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000024 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000025 return self.fileclass(self.text)
26
Jeremy Hylton8fff7922007-08-03 20:56:14 +000027class NoEOFStringIO(io.BytesIO):
Jeremy Hylton121d34a2003-07-08 12:36:58 +000028 """Like StringIO, but raises AssertionError on EOF.
29
30 This is used below to test that httplib doesn't try to read
31 more from the underlying file than it should.
32 """
33 def read(self, n=-1):
Jeremy Hylton8fff7922007-08-03 20:56:14 +000034 data = io.BytesIO.read(self, n)
Jeremy Hyltonda3f2282007-08-29 17:26:34 +000035 if data == b'':
Jeremy Hylton121d34a2003-07-08 12:36:58 +000036 raise AssertionError('caller tried to read past EOF')
37 return data
38
39 def readline(self, length=None):
Jeremy Hylton8fff7922007-08-03 20:56:14 +000040 data = io.BytesIO.readline(self, length)
Jeremy Hyltonda3f2282007-08-29 17:26:34 +000041 if data == b'':
Jeremy Hylton121d34a2003-07-08 12:36:58 +000042 raise AssertionError('caller tried to read past EOF')
43 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000044
Jeremy Hylton2c178252004-08-07 16:28:14 +000045class HeaderTests(TestCase):
46 def test_auto_headers(self):
47 # Some headers are added automatically, but should not be added by
48 # .request() if they are explicitly set.
49
Jeremy Hylton2c178252004-08-07 16:28:14 +000050 class HeaderCountingBuffer(list):
51 def __init__(self):
52 self.count = {}
53 def append(self, item):
Guido van Rossum022c4742007-08-29 02:00:20 +000054 kv = item.split(b':')
Jeremy Hylton2c178252004-08-07 16:28:14 +000055 if len(kv) > 1:
56 # item is a 'Key: Value' header string
Martin v. Löwisdd5a8602007-06-30 09:22:09 +000057 lcKey = kv[0].decode('ascii').lower()
Jeremy Hylton2c178252004-08-07 16:28:14 +000058 self.count.setdefault(lcKey, 0)
59 self.count[lcKey] += 1
60 list.append(self, item)
61
62 for explicit_header in True, False:
63 for header in 'Content-length', 'Host', 'Accept-encoding':
64 conn = httplib.HTTPConnection('example.com')
65 conn.sock = FakeSocket('blahblahblah')
66 conn._buffer = HeaderCountingBuffer()
67
68 body = 'spamspamspam'
69 headers = {}
70 if explicit_header:
71 headers[header] = str(len(body))
72 conn.request('POST', '/', body, headers)
73 self.assertEqual(conn._buffer.count[header.lower()], 1)
74
Thomas Wouters89f507f2006-12-13 04:49:30 +000075class BasicTest(TestCase):
76 def test_status_lines(self):
77 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000078
Thomas Wouters89f507f2006-12-13 04:49:30 +000079 body = "HTTP/1.1 200 Ok\r\n\r\nText"
80 sock = FakeSocket(body)
81 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000082 resp.begin()
Jeremy Hylton8fff7922007-08-03 20:56:14 +000083 self.assertEqual(resp.read(), b"Text")
Guido van Rossum8ce8a782007-11-01 19:42:39 +000084 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000085
Thomas Wouters89f507f2006-12-13 04:49:30 +000086 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
87 sock = FakeSocket(body)
88 resp = httplib.HTTPResponse(sock)
89 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000090
Guido van Rossum8ce8a782007-11-01 19:42:39 +000091 def test_partial_reads(self):
92 # if we have a lenght, the system knows when to close itself
93 # same behaviour than when we read the whole thing with read()
94 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
95 sock = FakeSocket(body)
96 resp = httplib.HTTPResponse(sock)
97 resp.begin()
98 self.assertEqual(resp.read(2), b'Te')
99 self.assertFalse(resp.isclosed())
100 self.assertEqual(resp.read(2), b'xt')
101 self.assertTrue(resp.isclosed())
102
Thomas Wouters89f507f2006-12-13 04:49:30 +0000103 def test_host_port(self):
104 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000105
Thomas Wouters89f507f2006-12-13 04:49:30 +0000106 for hp in ("www.python.org:abc", "www.python.org:"):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000107 self.assertRaises(httplib.InvalidURL, httplib.HTTPConnection, hp)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000108
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000109 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000",
110 "fe80::207:e9ff:fe9b", 8000),
Thomas Wouters89f507f2006-12-13 04:49:30 +0000111 ("www.python.org:80", "www.python.org", 80),
112 ("www.python.org", "www.python.org", 80),
113 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000114 c = httplib.HTTPConnection(hp)
115 self.assertEqual(h, c.host)
116 self.assertEqual(p, c.port)
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000117
Thomas Wouters89f507f2006-12-13 04:49:30 +0000118 def test_response_headers(self):
119 # test response with multiple message headers with the same field name.
120 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000121 'Set-Cookie: Customer="WILE_E_COYOTE"; '
122 'Version="1"; Path="/acme"\r\n'
Thomas Wouters89f507f2006-12-13 04:49:30 +0000123 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
124 ' Path="/acme"\r\n'
125 '\r\n'
126 'No body\r\n')
127 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
128 ', '
129 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
130 s = FakeSocket(text)
131 r = httplib.HTTPResponse(s)
132 r.begin()
133 cookies = r.getheader("Set-Cookie")
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000134 self.assertEqual(cookies, hdr)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000135
Thomas Wouters89f507f2006-12-13 04:49:30 +0000136 def test_read_head(self):
137 # Test that the library doesn't attempt to read any data
138 # from a HEAD request. (Tickles SF bug #622042.)
139 sock = FakeSocket(
140 'HTTP/1.1 200 OK\r\n'
141 'Content-Length: 14432\r\n'
142 '\r\n',
143 NoEOFStringIO)
144 resp = httplib.HTTPResponse(sock, method="HEAD")
145 resp.begin()
Guido van Rossuma00f1232007-09-12 19:43:09 +0000146 if resp.read():
Thomas Wouters89f507f2006-12-13 04:49:30 +0000147 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000148
Thomas Wouters89f507f2006-12-13 04:49:30 +0000149 def test_send_file(self):
Guido van Rossum022c4742007-08-29 02:00:20 +0000150 expected = (b'GET /foo HTTP/1.1\r\nHost: example.com\r\n'
151 b'Accept-Encoding: identity\r\nContent-Length:')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000152
153 body = open(__file__, 'rb')
154 conn = httplib.HTTPConnection('example.com')
155 sock = FakeSocket(body)
156 conn.sock = sock
157 conn.request('GET', '/foo', body)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000158 self.assertTrue(sock.data.startswith(expected), '%r != %r' %
159 (sock.data[:len(expected)], expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000160
Christian Heimesa612dc02008-02-24 13:08:18 +0000161 def test_chunked(self):
162 chunked_start = (
163 'HTTP/1.1 200 OK\r\n'
164 'Transfer-Encoding: chunked\r\n\r\n'
165 'a\r\n'
166 'hello worl\r\n'
167 '1\r\n'
168 'd\r\n'
169 )
170 sock = FakeSocket(chunked_start + '0\r\n')
171 resp = httplib.HTTPResponse(sock, method="GET")
172 resp.begin()
173 self.assertEquals(resp.read(), b'hello world')
174 resp.close()
175
176 for x in ('', 'foo\r\n'):
177 sock = FakeSocket(chunked_start + x)
178 resp = httplib.HTTPResponse(sock, method="GET")
179 resp.begin()
180 try:
181 resp.read()
182 except httplib.IncompleteRead as i:
183 self.assertEquals(i.partial, b'hello world')
Benjamin Peterson6accb982009-03-02 22:50:25 +0000184 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
185 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Christian Heimesa612dc02008-02-24 13:08:18 +0000186 else:
187 self.fail('IncompleteRead expected')
188 finally:
189 resp.close()
190
191 def test_negative_content_length(self):
Jeremy Hylton82066952008-12-15 03:08:30 +0000192 sock = FakeSocket(
193 'HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n')
Christian Heimesa612dc02008-02-24 13:08:18 +0000194 resp = httplib.HTTPResponse(sock, method="GET")
195 resp.begin()
196 self.assertEquals(resp.read(), b'Hello\r\n')
197 resp.close()
198
Benjamin Peterson6accb982009-03-02 22:50:25 +0000199 def test_incomplete_read(self):
200 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
201 resp = httplib.HTTPResponse(sock, method="GET")
202 resp.begin()
203 try:
204 resp.read()
205 except httplib.IncompleteRead as i:
206 self.assertEquals(i.partial, b'Hello\r\n')
207 self.assertEqual(repr(i),
208 "IncompleteRead(7 bytes read, 3 more expected)")
209 self.assertEqual(str(i),
210 "IncompleteRead(7 bytes read, 3 more expected)")
211 else:
212 self.fail('IncompleteRead expected')
213 finally:
214 resp.close()
215
Christian Heimesa612dc02008-02-24 13:08:18 +0000216
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000217class OfflineTest(TestCase):
218 def test_responses(self):
219 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
220
Guido van Rossumd8faa362007-04-27 19:54:29 +0000221class TimeoutTest(TestCase):
Christian Heimes5e696852008-04-09 08:37:03 +0000222 PORT = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000223
224 def setUp(self):
225 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000226 TimeoutTest.PORT = support.bind_port(self.serv)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000227 self.serv.listen(5)
228
229 def tearDown(self):
230 self.serv.close()
231 self.serv = None
232
233 def testTimeoutAttribute(self):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000234 # This will prove that the timeout gets through HTTPConnection
235 # and into the socket.
236
Georg Brandlf78e02b2008-06-10 17:40:04 +0000237 # default -- use global socket timeout
238 self.assert_(socket.getdefaulttimeout() is None)
239 socket.setdefaulttimeout(30)
240 try:
241 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
242 httpConn.connect()
243 finally:
244 socket.setdefaulttimeout(None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000245 self.assertEqual(httpConn.sock.gettimeout(), 30)
246 httpConn.close()
247
Georg Brandlf78e02b2008-06-10 17:40:04 +0000248 # no timeout -- do not use global socket default
249 self.assert_(socket.getdefaulttimeout() is None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000250 socket.setdefaulttimeout(30)
251 try:
Christian Heimes5e696852008-04-09 08:37:03 +0000252 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
253 timeout=None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000254 httpConn.connect()
255 finally:
Georg Brandlf78e02b2008-06-10 17:40:04 +0000256 socket.setdefaulttimeout(None)
257 self.assertEqual(httpConn.sock.gettimeout(), None)
258 httpConn.close()
259
260 # a value
261 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
262 httpConn.connect()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000263 self.assertEqual(httpConn.sock.gettimeout(), 30)
264 httpConn.close()
265
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000266class HTTPSTimeoutTest(TestCase):
267# XXX Here should be tests for HTTPS, there isn't any right now!
268
269 def test_attributes(self):
270 # simple test to check it's storing it
Thomas Wouters582b5862007-08-30 22:39:17 +0000271 if hasattr(httplib, 'HTTPSConnection'):
Christian Heimes5e696852008-04-09 08:37:03 +0000272 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters582b5862007-08-30 22:39:17 +0000273 self.assertEqual(h.timeout, 30)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000274
Jeremy Hylton2c178252004-08-07 16:28:14 +0000275def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000276 support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Antoine Pitroub353c122009-02-11 00:39:14 +0000277 HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000278
Thomas Wouters89f507f2006-12-13 04:49:30 +0000279if __name__ == '__main__':
280 test_main()