blob: 67719fd5e0023b7a6edf6ee8c7710777d2bd51ac [file] [log] [blame]
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00001import httplib
2import StringIO
Facundo Batista07c78be2007-03-23 18:54:07 +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
9class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000010 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000011 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000012 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000013 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000014
Jeremy Hylton2c178252004-08-07 16:28:14 +000015 def sendall(self, data):
Martin v. Löwis040a9272006-11-12 10:32:47 +000016 self.data += data
Jeremy Hylton2c178252004-08-07 16:28:14 +000017
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000018 def makefile(self, mode, bufsize=None):
19 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000020 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000021 return self.fileclass(self.text)
22
23class NoEOFStringIO(StringIO.StringIO):
24 """Like StringIO, but raises AssertionError on EOF.
25
26 This is used below to test that httplib doesn't try to read
27 more from the underlying file than it should.
28 """
29 def read(self, n=-1):
30 data = StringIO.StringIO.read(self, n)
31 if data == '':
32 raise AssertionError('caller tried to read past EOF')
33 return data
34
35 def readline(self, length=None):
36 data = StringIO.StringIO.readline(self, length)
37 if data == '':
38 raise AssertionError('caller tried to read past EOF')
39 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000040
Jeremy Hylton2c178252004-08-07 16:28:14 +000041
42class HeaderTests(TestCase):
43 def test_auto_headers(self):
44 # Some headers are added automatically, but should not be added by
45 # .request() if they are explicitly set.
46
47 import httplib
48
49 class HeaderCountingBuffer(list):
50 def __init__(self):
51 self.count = {}
52 def append(self, item):
53 kv = item.split(':')
54 if len(kv) > 1:
55 # item is a 'Key: Value' header string
56 lcKey = kv[0].lower()
57 self.count.setdefault(lcKey, 0)
58 self.count[lcKey] += 1
59 list.append(self, item)
60
61 for explicit_header in True, False:
62 for header in 'Content-length', 'Host', 'Accept-encoding':
63 conn = httplib.HTTPConnection('example.com')
64 conn.sock = FakeSocket('blahblahblah')
65 conn._buffer = HeaderCountingBuffer()
66
67 body = 'spamspamspam'
68 headers = {}
69 if explicit_header:
70 headers[header] = str(len(body))
71 conn.request('POST', '/', body, headers)
72 self.assertEqual(conn._buffer.count[header.lower()], 1)
73
Georg Brandl71a20892006-10-29 20:24:01 +000074class BasicTest(TestCase):
75 def test_status_lines(self):
76 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000077
Georg Brandl71a20892006-10-29 20:24:01 +000078 body = "HTTP/1.1 200 Ok\r\n\r\nText"
79 sock = FakeSocket(body)
80 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +000081 resp.begin()
Georg Brandl71a20892006-10-29 20:24:01 +000082 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +000083 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +000084
Georg Brandl71a20892006-10-29 20:24:01 +000085 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
86 sock = FakeSocket(body)
87 resp = httplib.HTTPResponse(sock)
88 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +000089
Facundo Batista70665902007-10-18 03:16:03 +000090 def test_partial_reads(self):
91 # if we have a lenght, the system knows when to close itself
92 # same behaviour than when we read the whole thing with read()
93 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
94 sock = FakeSocket(body)
95 resp = httplib.HTTPResponse(sock)
96 resp.begin()
97 self.assertEqual(resp.read(2), 'Te')
98 self.assertFalse(resp.isclosed())
99 self.assertEqual(resp.read(2), 'xt')
100 self.assertTrue(resp.isclosed())
101
Georg Brandl71a20892006-10-29 20:24:01 +0000102 def test_host_port(self):
103 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000104
Georg Brandl71a20892006-10-29 20:24:01 +0000105 for hp in ("www.python.org:abc", "www.python.org:"):
106 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
107
108 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000),
109 ("www.python.org:80", "www.python.org", 80),
110 ("www.python.org", "www.python.org", 80),
111 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000112 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000113 c = http._conn
114 if h != c.host: self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
115 if p != c.port: self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000116
Georg Brandl71a20892006-10-29 20:24:01 +0000117 def test_response_headers(self):
118 # test response with multiple message headers with the same field name.
119 text = ('HTTP/1.1 200 OK\r\n'
120 'Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r\n'
121 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
122 ' Path="/acme"\r\n'
123 '\r\n'
124 'No body\r\n')
125 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
126 ', '
127 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
128 s = FakeSocket(text)
129 r = httplib.HTTPResponse(s)
130 r.begin()
131 cookies = r.getheader("Set-Cookie")
132 if cookies != hdr:
133 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000134
Georg Brandl71a20892006-10-29 20:24:01 +0000135 def test_read_head(self):
136 # Test that the library doesn't attempt to read any data
137 # from a HEAD request. (Tickles SF bug #622042.)
138 sock = FakeSocket(
139 'HTTP/1.1 200 OK\r\n'
140 'Content-Length: 14432\r\n'
141 '\r\n',
142 NoEOFStringIO)
143 resp = httplib.HTTPResponse(sock, method="HEAD")
144 resp.begin()
145 if resp.read() != "":
146 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000147
Martin v. Löwis040a9272006-11-12 10:32:47 +0000148 def test_send_file(self):
149 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
150 'Accept-Encoding: identity\r\nContent-Length:'
151
152 body = open(__file__, 'rb')
153 conn = httplib.HTTPConnection('example.com')
154 sock = FakeSocket(body)
155 conn.sock = sock
156 conn.request('GET', '/foo', body)
157 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000158
Georg Brandl23635032008-02-24 00:03:22 +0000159 def test_chunked(self):
160 chunked_start = (
161 'HTTP/1.1 200 OK\r\n'
162 'Transfer-Encoding: chunked\r\n\r\n'
163 'a\r\n'
164 'hello worl\r\n'
165 '1\r\n'
166 'd\r\n'
167 )
168 sock = FakeSocket(chunked_start + '0\r\n')
169 resp = httplib.HTTPResponse(sock, method="GET")
170 resp.begin()
171 self.assertEquals(resp.read(), 'hello world')
172 resp.close()
173
174 for x in ('', 'foo\r\n'):
175 sock = FakeSocket(chunked_start + x)
176 resp = httplib.HTTPResponse(sock, method="GET")
177 resp.begin()
178 try:
179 resp.read()
180 except httplib.IncompleteRead, i:
181 self.assertEquals(i.partial, 'hello world')
182 else:
183 self.fail('IncompleteRead expected')
184 finally:
185 resp.close()
186
Georg Brandl8c460d52008-02-24 00:14:24 +0000187 def test_negative_content_length(self):
188 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n')
189 resp = httplib.HTTPResponse(sock, method="GET")
190 resp.begin()
191 self.assertEquals(resp.read(), 'Hello\r\n')
192 resp.close()
193
Georg Brandl23635032008-02-24 00:03:22 +0000194
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000195class OfflineTest(TestCase):
196 def test_responses(self):
197 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
198
Facundo Batista07c78be2007-03-23 18:54:07 +0000199PORT = 50003
200HOST = "localhost"
201
202class TimeoutTest(TestCase):
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000203
Facundo Batista07c78be2007-03-23 18:54:07 +0000204 def setUp(self):
205 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
206 self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
207 global PORT
208 PORT = test_support.bind_port(self.serv, HOST, PORT)
Facundo Batistaf1966292007-03-25 03:20:05 +0000209 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000210
211 def tearDown(self):
212 self.serv.close()
213 self.serv = None
214
215 def testTimeoutAttribute(self):
216 '''This will prove that the timeout gets through
217 HTTPConnection and into the socket.
218 '''
219 # default
220 httpConn = httplib.HTTPConnection(HOST, PORT)
221 httpConn.connect()
222 self.assertTrue(httpConn.sock.gettimeout() is None)
Facundo Batistaf1966292007-03-25 03:20:05 +0000223 httpConn.close()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000224
Facundo Batista07c78be2007-03-23 18:54:07 +0000225 # a value
Facundo Batista14553b02007-03-23 20:23:08 +0000226 httpConn = httplib.HTTPConnection(HOST, PORT, timeout=30)
Facundo Batista07c78be2007-03-23 18:54:07 +0000227 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000228 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000229 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000230
231 # None, having other default
232 previous = socket.getdefaulttimeout()
Facundo Batista14553b02007-03-23 20:23:08 +0000233 socket.setdefaulttimeout(30)
234 try:
235 httpConn = httplib.HTTPConnection(HOST, PORT, timeout=None)
236 httpConn.connect()
237 finally:
238 socket.setdefaulttimeout(previous)
239 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000240 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000241
242
Facundo Batista70f996b2007-05-21 17:32:32 +0000243class HTTPSTimeoutTest(TestCase):
244# XXX Here should be tests for HTTPS, there isn't any right now!
245
246 def test_attributes(self):
247 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000248 if hasattr(httplib, 'HTTPSConnection'):
249 h = httplib.HTTPSConnection(HOST, PORT, timeout=30)
250 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000251
Jeremy Hylton2c178252004-08-07 16:28:14 +0000252def test_main(verbose=None):
Facundo Batista70f996b2007-05-21 17:32:32 +0000253 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, HTTPSTimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000254
Georg Brandl71a20892006-10-29 20:24:01 +0000255if __name__ == '__main__':
256 test_main()