blob: a39a3eb501613e9ea8863f94b0b114ef3ce2955d [file] [log] [blame]
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00001import httplib
2import StringIO
Jeremy Hylton121d34a2003-07-08 12:36:58 +00003import sys
Facundo Batista07c78be2007-03-23 18:54:07 +00004import socket
Jeremy Hylton121d34a2003-07-08 12:36:58 +00005
Jeremy Hylton2c178252004-08-07 16:28:14 +00006from unittest import TestCase
7
8from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00009
10class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000011 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000012 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000013 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000014 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000015
Jeremy Hylton2c178252004-08-07 16:28:14 +000016 def sendall(self, data):
Martin v. Löwis040a9272006-11-12 10:32:47 +000017 self.data += data
Jeremy Hylton2c178252004-08-07 16:28:14 +000018
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000019 def makefile(self, mode, bufsize=None):
20 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000021 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000022 return self.fileclass(self.text)
23
24class NoEOFStringIO(StringIO.StringIO):
25 """Like StringIO, but raises AssertionError on EOF.
26
27 This is used below to test that httplib doesn't try to read
28 more from the underlying file than it should.
29 """
30 def read(self, n=-1):
31 data = StringIO.StringIO.read(self, n)
32 if data == '':
33 raise AssertionError('caller tried to read past EOF')
34 return data
35
36 def readline(self, length=None):
37 data = StringIO.StringIO.readline(self, length)
38 if data == '':
39 raise AssertionError('caller tried to read past EOF')
40 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000041
Jeremy Hylton2c178252004-08-07 16:28:14 +000042
43class HeaderTests(TestCase):
44 def test_auto_headers(self):
45 # Some headers are added automatically, but should not be added by
46 # .request() if they are explicitly set.
47
48 import httplib
49
50 class HeaderCountingBuffer(list):
51 def __init__(self):
52 self.count = {}
53 def append(self, item):
54 kv = item.split(':')
55 if len(kv) > 1:
56 # item is a 'Key: Value' header string
57 lcKey = kv[0].lower()
58 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
Georg Brandl71a20892006-10-29 20:24:01 +000075class BasicTest(TestCase):
76 def test_status_lines(self):
77 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000078
Georg Brandl71a20892006-10-29 20:24:01 +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()
Georg Brandl71a20892006-10-29 20:24:01 +000083 self.assertEqual(resp.read(), 'Text')
84 resp.close()
Jeremy Hyltonba603192003-01-23 18:02:20 +000085
Georg Brandl71a20892006-10-29 20:24:01 +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
Georg Brandl71a20892006-10-29 20:24:01 +000091 def test_host_port(self):
92 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +000093
Georg Brandl71a20892006-10-29 20:24:01 +000094 for hp in ("www.python.org:abc", "www.python.org:"):
95 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
96
97 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000),
98 ("www.python.org:80", "www.python.org", 80),
99 ("www.python.org", "www.python.org", 80),
100 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000101 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000102 c = http._conn
103 if h != c.host: self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
104 if p != c.port: self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000105
Georg Brandl71a20892006-10-29 20:24:01 +0000106 def test_response_headers(self):
107 # test response with multiple message headers with the same field name.
108 text = ('HTTP/1.1 200 OK\r\n'
109 'Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r\n'
110 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
111 ' Path="/acme"\r\n'
112 '\r\n'
113 'No body\r\n')
114 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
115 ', '
116 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
117 s = FakeSocket(text)
118 r = httplib.HTTPResponse(s)
119 r.begin()
120 cookies = r.getheader("Set-Cookie")
121 if cookies != hdr:
122 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000123
Georg Brandl71a20892006-10-29 20:24:01 +0000124 def test_read_head(self):
125 # Test that the library doesn't attempt to read any data
126 # from a HEAD request. (Tickles SF bug #622042.)
127 sock = FakeSocket(
128 'HTTP/1.1 200 OK\r\n'
129 'Content-Length: 14432\r\n'
130 '\r\n',
131 NoEOFStringIO)
132 resp = httplib.HTTPResponse(sock, method="HEAD")
133 resp.begin()
134 if resp.read() != "":
135 self.fail("Did not expect response from HEAD request")
136 resp.close()
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000137
Martin v. Löwis040a9272006-11-12 10:32:47 +0000138 def test_send_file(self):
139 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
140 'Accept-Encoding: identity\r\nContent-Length:'
141
142 body = open(__file__, 'rb')
143 conn = httplib.HTTPConnection('example.com')
144 sock = FakeSocket(body)
145 conn.sock = sock
146 conn.request('GET', '/foo', body)
147 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000148
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000149class OfflineTest(TestCase):
150 def test_responses(self):
151 self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
152
Facundo Batista07c78be2007-03-23 18:54:07 +0000153PORT = 50003
154HOST = "localhost"
155
156class TimeoutTest(TestCase):
157
158 def setUp(self):
159 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
160 self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
161 global PORT
162 PORT = test_support.bind_port(self.serv, HOST, PORT)
163 self.serv.listen(1)
164
165 def tearDown(self):
166 self.serv.close()
167 self.serv = None
168
169 def testTimeoutAttribute(self):
170 '''This will prove that the timeout gets through
171 HTTPConnection and into the socket.
172 '''
173 # default
174 httpConn = httplib.HTTPConnection(HOST, PORT)
175 httpConn.connect()
176 self.assertTrue(httpConn.sock.gettimeout() is None)
177
178 # a value
179 httpConn = httplib.HTTPConnection(HOST, PORT, timeout=10)
180 httpConn.connect()
181 self.assertEqual(httpConn.sock.gettimeout(), 10)
182
183 # None, having other default
184 previous = socket.getdefaulttimeout()
185 socket.setdefaulttimeout(10)
186 httpConn = httplib.HTTPConnection(HOST, PORT, timeout=None)
187 httpConn.connect()
188 socket.setdefaulttimeout(previous)
189 self.assertEqual(httpConn.sock.gettimeout(), 10)
190
191
Jeremy Hylton2c178252004-08-07 16:28:14 +0000192def test_main(verbose=None):
Facundo Batista07c78be2007-03-23 18:54:07 +0000193 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000194
Georg Brandl71a20892006-10-29 20:24:01 +0000195if __name__ == '__main__':
196 test_main()