blob: ede0f4b82f99289141d5fcc7e75a6e2db623204d [file] [log] [blame]
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00001import httplib
2import StringIO
Jeremy Hylton121d34a2003-07-08 12:36:58 +00003import sys
4
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
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000013
Jeremy Hylton2c178252004-08-07 16:28:14 +000014 def sendall(self, data):
15 self.data = data
16
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000017 def makefile(self, mode, bufsize=None):
18 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000019 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000020 return self.fileclass(self.text)
21
22class NoEOFStringIO(StringIO.StringIO):
23 """Like StringIO, but raises AssertionError on EOF.
24
25 This is used below to test that httplib doesn't try to read
26 more from the underlying file than it should.
27 """
28 def read(self, n=-1):
29 data = StringIO.StringIO.read(self, n)
30 if data == '':
31 raise AssertionError('caller tried to read past EOF')
32 return data
33
34 def readline(self, length=None):
35 data = StringIO.StringIO.readline(self, length)
36 if data == '':
37 raise AssertionError('caller tried to read past EOF')
38 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000039
Jeremy Hylton2c178252004-08-07 16:28:14 +000040
41class HeaderTests(TestCase):
42 def test_auto_headers(self):
43 # Some headers are added automatically, but should not be added by
44 # .request() if they are explicitly set.
45
46 import httplib
47
48 class HeaderCountingBuffer(list):
49 def __init__(self):
50 self.count = {}
51 def append(self, item):
52 kv = item.split(':')
53 if len(kv) > 1:
54 # item is a 'Key: Value' header string
55 lcKey = kv[0].lower()
56 self.count.setdefault(lcKey, 0)
57 self.count[lcKey] += 1
58 list.append(self, item)
59
60 for explicit_header in True, False:
61 for header in 'Content-length', 'Host', 'Accept-encoding':
62 conn = httplib.HTTPConnection('example.com')
63 conn.sock = FakeSocket('blahblahblah')
64 conn._buffer = HeaderCountingBuffer()
65
66 body = 'spamspamspam'
67 headers = {}
68 if explicit_header:
69 headers[header] = str(len(body))
70 conn.request('POST', '/', body, headers)
71 self.assertEqual(conn._buffer.count[header.lower()], 1)
72
Jeremy Hyltonba603192003-01-23 18:02:20 +000073# Collect output to a buffer so that we don't have to cope with line-ending
74# issues across platforms. Specifically, the headers will have \r\n pairs
75# and some platforms will strip them from the output file.
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000076
Jeremy Hyltonba603192003-01-23 18:02:20 +000077def test():
78 buf = StringIO.StringIO()
79 _stdout = sys.stdout
Skip Montanaro03ff86d2002-03-24 16:54:16 +000080 try:
Jeremy Hyltonba603192003-01-23 18:02:20 +000081 sys.stdout = buf
82 _test()
83 finally:
84 sys.stdout = _stdout
Jeremy Hylton6d0a4c72002-07-07 16:51:37 +000085
Jeremy Hyltonba603192003-01-23 18:02:20 +000086 # print individual lines with endings stripped
87 s = buf.getvalue()
88 for line in s.split("\n"):
89 print line.strip()
90
91def _test():
92 # Test HTTP status lines
93
94 body = "HTTP/1.1 200 Ok\r\n\r\nText"
95 sock = FakeSocket(body)
96 resp = httplib.HTTPResponse(sock, 1)
97 resp.begin()
98 print resp.read()
99 resp.close()
100
101 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
102 sock = FakeSocket(body)
103 resp = httplib.HTTPResponse(sock, 1)
104 try:
105 resp.begin()
106 except httplib.BadStatusLine:
107 print "BadStatusLine raised as expected"
108 else:
109 print "Expect BadStatusLine"
110
111 # Check invalid host_port
112
113 for hp in ("www.python.org:abc", "www.python.org:"):
114 try:
115 h = httplib.HTTP(hp)
116 except httplib.InvalidURL:
117 print "InvalidURL raised as expected"
118 else:
119 print "Expect InvalidURL"
120
Tim Petersc74298a2004-09-16 00:09:19 +0000121 for hp,h,p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", 8000),
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000122 ("www.python.org:80", "www.python.org", 80),
123 ("www.python.org", "www.python.org", 80),
Brett Cannon0a1af4a2004-09-15 23:26:23 +0000124 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000125 try:
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000126 http = httplib.HTTP(hp)
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000127 except httplib.InvalidURL:
128 print "InvalidURL raised erroneously"
Brett Cannon0a1af4a2004-09-15 23:26:23 +0000129 c = http._conn
130 if h != c.host: raise AssertionError, ("Host incorrectly parsed", h, c.host)
131 if p != c.port: raise AssertionError, ("Port incorrectly parsed", p, c.host)
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000132
Jeremy Hyltonba603192003-01-23 18:02:20 +0000133 # test response with multiple message headers with the same field name.
134 text = ('HTTP/1.1 200 OK\r\n'
135 'Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r\n'
136 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
137 ' Path="/acme"\r\n'
138 '\r\n'
139 'No body\r\n')
140 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
141 ', '
142 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
143 s = FakeSocket(text)
144 r = httplib.HTTPResponse(s, 1)
145 r.begin()
146 cookies = r.getheader("Set-Cookie")
147 if cookies != hdr:
148 raise AssertionError, "multiple headers not combined properly"
149
Jeremy Hylton121d34a2003-07-08 12:36:58 +0000150 # Test that the library doesn't attempt to read any data
151 # from a HEAD request. (Tickles SF bug #622042.)
152 sock = FakeSocket(
153 'HTTP/1.1 200 OK\r\n'
154 'Content-Length: 14432\r\n'
155 '\r\n',
156 NoEOFStringIO)
157 resp = httplib.HTTPResponse(sock, 1, method="HEAD")
158 resp.begin()
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000159 if resp.read() != "":
160 raise AssertionError, "Did not expect response from HEAD request"
161 resp.close()
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000162
Jeremy Hylton2c178252004-08-07 16:28:14 +0000163
164def test_main(verbose=None):
165 tests = [HeaderTests,]
166 test_support.run_unittest(*tests)
167
Jeremy Hyltonba603192003-01-23 18:02:20 +0000168test()