blob: 591f95684d9796d58313f40dc12ed5086802f1b0 [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 +000045
46class HeaderTests(TestCase):
47 def test_auto_headers(self):
48 # Some headers are added automatically, but should not be added by
49 # .request() if they are explicitly set.
50
Jeremy Hylton2c178252004-08-07 16:28:14 +000051 class HeaderCountingBuffer(list):
52 def __init__(self):
53 self.count = {}
54 def append(self, item):
Guido van Rossum022c4742007-08-29 02:00:20 +000055 kv = item.split(b':')
Jeremy Hylton2c178252004-08-07 16:28:14 +000056 if len(kv) > 1:
57 # item is a 'Key: Value' header string
Martin v. Löwisdd5a8602007-06-30 09:22:09 +000058 lcKey = kv[0].decode('ascii').lower()
Jeremy Hylton2c178252004-08-07 16:28:14 +000059 self.count.setdefault(lcKey, 0)
60 self.count[lcKey] += 1
61 list.append(self, item)
62
63 for explicit_header in True, False:
64 for header in 'Content-length', 'Host', 'Accept-encoding':
65 conn = httplib.HTTPConnection('example.com')
66 conn.sock = FakeSocket('blahblahblah')
67 conn._buffer = HeaderCountingBuffer()
68
69 body = 'spamspamspam'
70 headers = {}
71 if explicit_header:
72 headers[header] = str(len(body))
73 conn.request('POST', '/', body, headers)
74 self.assertEqual(conn._buffer.count[header.lower()], 1)
75
Thomas Wouters89f507f2006-12-13 04:49:30 +000076class BasicTest(TestCase):
77 def test_status_lines(self):
78 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000079
Thomas Wouters89f507f2006-12-13 04:49:30 +000080 body = "HTTP/1.1 200 Ok\r\n\r\nText"
81 sock = FakeSocket(body)
82 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000083 resp.begin()
Jeremy Hylton8fff7922007-08-03 20:56:14 +000084 self.assertEqual(resp.read(), b"Text")
Guido van Rossum8ce8a782007-11-01 19:42:39 +000085 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000086
Thomas Wouters89f507f2006-12-13 04:49:30 +000087 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
88 sock = FakeSocket(body)
89 resp = httplib.HTTPResponse(sock)
90 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000091
Guido van Rossum8ce8a782007-11-01 19:42:39 +000092 def test_partial_reads(self):
93 # if we have a lenght, the system knows when to close itself
94 # same behaviour than when we read the whole thing with read()
95 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
96 sock = FakeSocket(body)
97 resp = httplib.HTTPResponse(sock)
98 resp.begin()
99 self.assertEqual(resp.read(2), b'Te')
100 self.assertFalse(resp.isclosed())
101 self.assertEqual(resp.read(2), b'xt')
102 self.assertTrue(resp.isclosed())
103
Thomas Wouters89f507f2006-12-13 04:49:30 +0000104 def test_host_port(self):
105 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000106
Thomas Wouters89f507f2006-12-13 04:49:30 +0000107 for hp in ("www.python.org:abc", "www.python.org:"):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000108 self.assertRaises(httplib.InvalidURL, httplib.HTTPConnection, hp)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000109
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000110 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000",
111 "fe80::207:e9ff:fe9b", 8000),
Thomas Wouters89f507f2006-12-13 04:49:30 +0000112 ("www.python.org:80", "www.python.org", 80),
113 ("www.python.org", "www.python.org", 80),
114 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000115 c = httplib.HTTPConnection(hp)
116 self.assertEqual(h, c.host)
117 self.assertEqual(p, c.port)
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000118
Thomas Wouters89f507f2006-12-13 04:49:30 +0000119 def test_response_headers(self):
120 # test response with multiple message headers with the same field name.
121 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000122 'Set-Cookie: Customer="WILE_E_COYOTE"; '
123 'Version="1"; Path="/acme"\r\n'
Thomas Wouters89f507f2006-12-13 04:49:30 +0000124 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
125 ' Path="/acme"\r\n'
126 '\r\n'
127 'No body\r\n')
128 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
129 ', '
130 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
131 s = FakeSocket(text)
132 r = httplib.HTTPResponse(s)
133 r.begin()
134 cookies = r.getheader("Set-Cookie")
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000135 self.assertEqual(cookies, hdr)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000136
Thomas Wouters89f507f2006-12-13 04:49:30 +0000137 def test_read_head(self):
138 # Test that the library doesn't attempt to read any data
139 # from a HEAD request. (Tickles SF bug #622042.)
140 sock = FakeSocket(
141 'HTTP/1.1 200 OK\r\n'
142 'Content-Length: 14432\r\n'
143 '\r\n',
144 NoEOFStringIO)
145 resp = httplib.HTTPResponse(sock, method="HEAD")
146 resp.begin()
Guido van Rossuma00f1232007-09-12 19:43:09 +0000147 if resp.read():
Thomas Wouters89f507f2006-12-13 04:49:30 +0000148 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000149
Thomas Wouters89f507f2006-12-13 04:49:30 +0000150 def test_send_file(self):
Guido van Rossum022c4742007-08-29 02:00:20 +0000151 expected = (b'GET /foo HTTP/1.1\r\nHost: example.com\r\n'
152 b'Accept-Encoding: identity\r\nContent-Length:')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000153
154 body = open(__file__, 'rb')
155 conn = httplib.HTTPConnection('example.com')
156 sock = FakeSocket(body)
157 conn.sock = sock
158 conn.request('GET', '/foo', body)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000159 self.assertTrue(sock.data.startswith(expected), '%r != %r' %
160 (sock.data[:len(expected)], expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000161
Christian Heimesa612dc02008-02-24 13:08:18 +0000162 def test_chunked(self):
163 chunked_start = (
164 'HTTP/1.1 200 OK\r\n'
165 'Transfer-Encoding: chunked\r\n\r\n'
166 'a\r\n'
167 'hello worl\r\n'
168 '1\r\n'
169 'd\r\n'
170 )
171 sock = FakeSocket(chunked_start + '0\r\n')
172 resp = httplib.HTTPResponse(sock, method="GET")
173 resp.begin()
174 self.assertEquals(resp.read(), b'hello world')
175 resp.close()
176
177 for x in ('', 'foo\r\n'):
178 sock = FakeSocket(chunked_start + x)
179 resp = httplib.HTTPResponse(sock, method="GET")
180 resp.begin()
181 try:
182 resp.read()
183 except httplib.IncompleteRead as i:
184 self.assertEquals(i.partial, b'hello world')
185 else:
186 self.fail('IncompleteRead expected')
187 finally:
188 resp.close()
189
190 def test_negative_content_length(self):
Jeremy Hylton82066952008-12-15 03:08:30 +0000191 sock = FakeSocket(
192 'HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n')
Christian Heimesa612dc02008-02-24 13:08:18 +0000193 resp = httplib.HTTPResponse(sock, method="GET")
194 resp.begin()
195 self.assertEquals(resp.read(), b'Hello\r\n')
196 resp.close()
197
198
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000199class OfflineTest(TestCase):
200 def test_responses(self):
201 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
202
Guido van Rossumd8faa362007-04-27 19:54:29 +0000203class TimeoutTest(TestCase):
Christian Heimes5e696852008-04-09 08:37:03 +0000204 PORT = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205
206 def setUp(self):
207 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000208 TimeoutTest.PORT = support.bind_port(self.serv)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000209 self.serv.listen(5)
210
211 def tearDown(self):
212 self.serv.close()
213 self.serv = None
214
215 def testTimeoutAttribute(self):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000216 # This will prove that the timeout gets through HTTPConnection
217 # and into the socket.
218
Georg Brandlf78e02b2008-06-10 17:40:04 +0000219 # default -- use global socket timeout
220 self.assert_(socket.getdefaulttimeout() is None)
221 socket.setdefaulttimeout(30)
222 try:
223 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
224 httpConn.connect()
225 finally:
226 socket.setdefaulttimeout(None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000227 self.assertEqual(httpConn.sock.gettimeout(), 30)
228 httpConn.close()
229
Georg Brandlf78e02b2008-06-10 17:40:04 +0000230 # no timeout -- do not use global socket default
231 self.assert_(socket.getdefaulttimeout() is None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000232 socket.setdefaulttimeout(30)
233 try:
Christian Heimes5e696852008-04-09 08:37:03 +0000234 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
235 timeout=None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000236 httpConn.connect()
237 finally:
Georg Brandlf78e02b2008-06-10 17:40:04 +0000238 socket.setdefaulttimeout(None)
239 self.assertEqual(httpConn.sock.gettimeout(), None)
240 httpConn.close()
241
242 # a value
243 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
244 httpConn.connect()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000245 self.assertEqual(httpConn.sock.gettimeout(), 30)
246 httpConn.close()
247
248
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000249class HTTPSTimeoutTest(TestCase):
250# XXX Here should be tests for HTTPS, there isn't any right now!
251
252 def test_attributes(self):
253 # simple test to check it's storing it
Thomas Wouters582b5862007-08-30 22:39:17 +0000254 if hasattr(httplib, 'HTTPSConnection'):
Christian Heimes5e696852008-04-09 08:37:03 +0000255 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters582b5862007-08-30 22:39:17 +0000256 self.assertEqual(h.timeout, 30)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000257
Jeremy Hylton2c178252004-08-07 16:28:14 +0000258def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000259 support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Christian Heimes5e696852008-04-09 08:37:03 +0000260 HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000261
Thomas Wouters89f507f2006-12-13 04:49:30 +0000262if __name__ == '__main__':
263 test_main()