blob: f0e551f5eb3ace43ab982b4d82ccf65347033f34 [file] [log] [blame]
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00001import 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
7from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00008
Christian Heimes5e696852008-04-09 08:37:03 +00009HOST = test_support.HOST
10
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
51 import httplib
52
53 class HeaderCountingBuffer(list):
54 def __init__(self):
55 self.count = {}
56 def append(self, item):
Guido van Rossum022c4742007-08-29 02:00:20 +000057 kv = item.split(b':')
Jeremy Hylton2c178252004-08-07 16:28:14 +000058 if len(kv) > 1:
59 # item is a 'Key: Value' header string
Martin v. Löwisdd5a8602007-06-30 09:22:09 +000060 lcKey = kv[0].decode('ascii').lower()
Jeremy Hylton2c178252004-08-07 16:28:14 +000061 self.count.setdefault(lcKey, 0)
62 self.count[lcKey] += 1
63 list.append(self, item)
64
65 for explicit_header in True, False:
66 for header in 'Content-length', 'Host', 'Accept-encoding':
67 conn = httplib.HTTPConnection('example.com')
68 conn.sock = FakeSocket('blahblahblah')
69 conn._buffer = HeaderCountingBuffer()
70
71 body = 'spamspamspam'
72 headers = {}
73 if explicit_header:
74 headers[header] = str(len(body))
75 conn.request('POST', '/', body, headers)
76 self.assertEqual(conn._buffer.count[header.lower()], 1)
77
Thomas Wouters89f507f2006-12-13 04:49:30 +000078class BasicTest(TestCase):
79 def test_status_lines(self):
80 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000081
Thomas Wouters89f507f2006-12-13 04:49:30 +000082 body = "HTTP/1.1 200 Ok\r\n\r\nText"
83 sock = FakeSocket(body)
84 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000085 resp.begin()
Jeremy Hylton8fff7922007-08-03 20:56:14 +000086 self.assertEqual(resp.read(), b"Text")
Guido van Rossum8ce8a782007-11-01 19:42:39 +000087 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000088
Thomas Wouters89f507f2006-12-13 04:49:30 +000089 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
90 sock = FakeSocket(body)
91 resp = httplib.HTTPResponse(sock)
92 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000093
Guido van Rossum8ce8a782007-11-01 19:42:39 +000094 def test_partial_reads(self):
95 # if we have a lenght, the system knows when to close itself
96 # same behaviour than when we read the whole thing with read()
97 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
98 sock = FakeSocket(body)
99 resp = httplib.HTTPResponse(sock)
100 resp.begin()
101 self.assertEqual(resp.read(2), b'Te')
102 self.assertFalse(resp.isclosed())
103 self.assertEqual(resp.read(2), b'xt')
104 self.assertTrue(resp.isclosed())
105
Thomas Wouters89f507f2006-12-13 04:49:30 +0000106 def test_host_port(self):
107 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000108
Thomas Wouters89f507f2006-12-13 04:49:30 +0000109 for hp in ("www.python.org:abc", "www.python.org:"):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000110 self.assertRaises(httplib.InvalidURL, httplib.HTTPConnection, hp)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000111
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000112 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000",
113 "fe80::207:e9ff:fe9b", 8000),
Thomas Wouters89f507f2006-12-13 04:49:30 +0000114 ("www.python.org:80", "www.python.org", 80),
115 ("www.python.org", "www.python.org", 80),
116 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000117 c = httplib.HTTPConnection(hp)
118 self.assertEqual(h, c.host)
119 self.assertEqual(p, c.port)
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000120
Thomas Wouters89f507f2006-12-13 04:49:30 +0000121 def test_response_headers(self):
122 # test response with multiple message headers with the same field name.
123 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000124 'Set-Cookie: Customer="WILE_E_COYOTE"; '
125 'Version="1"; Path="/acme"\r\n'
Thomas Wouters89f507f2006-12-13 04:49:30 +0000126 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
127 ' Path="/acme"\r\n'
128 '\r\n'
129 'No body\r\n')
130 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
131 ', '
132 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
133 s = FakeSocket(text)
134 r = httplib.HTTPResponse(s)
135 r.begin()
136 cookies = r.getheader("Set-Cookie")
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000137 self.assertEqual(cookies, hdr)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000138
Thomas Wouters89f507f2006-12-13 04:49:30 +0000139 def test_read_head(self):
140 # Test that the library doesn't attempt to read any data
141 # from a HEAD request. (Tickles SF bug #622042.)
142 sock = FakeSocket(
143 'HTTP/1.1 200 OK\r\n'
144 'Content-Length: 14432\r\n'
145 '\r\n',
146 NoEOFStringIO)
147 resp = httplib.HTTPResponse(sock, method="HEAD")
148 resp.begin()
Guido van Rossuma00f1232007-09-12 19:43:09 +0000149 if resp.read():
Thomas Wouters89f507f2006-12-13 04:49:30 +0000150 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000151
Thomas Wouters89f507f2006-12-13 04:49:30 +0000152 def test_send_file(self):
Guido van Rossum022c4742007-08-29 02:00:20 +0000153 expected = (b'GET /foo HTTP/1.1\r\nHost: example.com\r\n'
154 b'Accept-Encoding: identity\r\nContent-Length:')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000155
156 body = open(__file__, 'rb')
157 conn = httplib.HTTPConnection('example.com')
158 sock = FakeSocket(body)
159 conn.sock = sock
160 conn.request('GET', '/foo', body)
Guido van Rossum98297ee2007-11-06 21:34:58 +0000161 self.assertTrue(sock.data.startswith(expected), '%r != %r' %
162 (sock.data[:len(expected)], expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000163
Christian Heimesa612dc02008-02-24 13:08:18 +0000164 def test_chunked(self):
165 chunked_start = (
166 'HTTP/1.1 200 OK\r\n'
167 'Transfer-Encoding: chunked\r\n\r\n'
168 'a\r\n'
169 'hello worl\r\n'
170 '1\r\n'
171 'd\r\n'
172 )
173 sock = FakeSocket(chunked_start + '0\r\n')
174 resp = httplib.HTTPResponse(sock, method="GET")
175 resp.begin()
176 self.assertEquals(resp.read(), b'hello world')
177 resp.close()
178
179 for x in ('', 'foo\r\n'):
180 sock = FakeSocket(chunked_start + x)
181 resp = httplib.HTTPResponse(sock, method="GET")
182 resp.begin()
183 try:
184 resp.read()
185 except httplib.IncompleteRead as i:
186 self.assertEquals(i.partial, b'hello world')
187 else:
188 self.fail('IncompleteRead expected')
189 finally:
190 resp.close()
191
192 def test_negative_content_length(self):
193 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n')
194 resp = httplib.HTTPResponse(sock, method="GET")
195 resp.begin()
196 self.assertEquals(resp.read(), b'Hello\r\n')
197 resp.close()
198
199
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000200class OfflineTest(TestCase):
201 def test_responses(self):
202 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
203
Guido van Rossumd8faa362007-04-27 19:54:29 +0000204class TimeoutTest(TestCase):
Christian Heimes5e696852008-04-09 08:37:03 +0000205 PORT = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000206
207 def setUp(self):
208 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Christian Heimes5e696852008-04-09 08:37:03 +0000209 TimeoutTest.PORT = test_support.bind_port(self.serv)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000210 self.serv.listen(5)
211
212 def tearDown(self):
213 self.serv.close()
214 self.serv = None
215
216 def testTimeoutAttribute(self):
Jeremy Hylton3a38c912007-08-14 17:08:07 +0000217 # This will prove that the timeout gets through HTTPConnection
218 # and into the socket.
219
Guido van Rossumd8faa362007-04-27 19:54:29 +0000220 # default
Christian Heimes5e696852008-04-09 08:37:03 +0000221 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000222 httpConn.connect()
223 self.assertTrue(httpConn.sock.gettimeout() is None)
224 httpConn.close()
225
226 # a value
Christian Heimes5e696852008-04-09 08:37:03 +0000227 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000228 httpConn.connect()
229 self.assertEqual(httpConn.sock.gettimeout(), 30)
230 httpConn.close()
231
232 # None, having other default
233 previous = socket.getdefaulttimeout()
234 socket.setdefaulttimeout(30)
235 try:
Christian Heimes5e696852008-04-09 08:37:03 +0000236 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
237 timeout=None)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000238 httpConn.connect()
239 finally:
240 socket.setdefaulttimeout(previous)
241 self.assertEqual(httpConn.sock.gettimeout(), 30)
242 httpConn.close()
243
244
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000245class HTTPSTimeoutTest(TestCase):
246# XXX Here should be tests for HTTPS, there isn't any right now!
247
248 def test_attributes(self):
249 # simple test to check it's storing it
Thomas Wouters582b5862007-08-30 22:39:17 +0000250 if hasattr(httplib, 'HTTPSConnection'):
Christian Heimes5e696852008-04-09 08:37:03 +0000251 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters582b5862007-08-30 22:39:17 +0000252 self.assertEqual(h.timeout, 30)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000253
Jeremy Hylton2c178252004-08-07 16:28:14 +0000254def test_main(verbose=None):
Christian Heimes5e696852008-04-09 08:37:03 +0000255 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
256 HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000257
Thomas Wouters89f507f2006-12-13 04:49:30 +0000258if __name__ == '__main__':
259 test_main()