blob: b49f71d2e33c0857cb634b9a6952465ceb72d29d [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
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000121 for hp in ("[fe80::207:e9ff:fe9b]:8000", "www.python.org:80",
122 "www.python.org"):
123 try:
124 h = httplib.HTTP(hp)
125 except httplib.InvalidURL:
126 print "InvalidURL raised erroneously"
127
Jeremy Hyltonba603192003-01-23 18:02:20 +0000128 # test response with multiple message headers with the same field name.
129 text = ('HTTP/1.1 200 OK\r\n'
130 'Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r\n'
131 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
132 ' Path="/acme"\r\n'
133 '\r\n'
134 'No body\r\n')
135 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
136 ', '
137 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
138 s = FakeSocket(text)
139 r = httplib.HTTPResponse(s, 1)
140 r.begin()
141 cookies = r.getheader("Set-Cookie")
142 if cookies != hdr:
143 raise AssertionError, "multiple headers not combined properly"
144
Jeremy Hylton121d34a2003-07-08 12:36:58 +0000145 # Test that the library doesn't attempt to read any data
146 # from a HEAD request. (Tickles SF bug #622042.)
147 sock = FakeSocket(
148 'HTTP/1.1 200 OK\r\n'
149 'Content-Length: 14432\r\n'
150 '\r\n',
151 NoEOFStringIO)
152 resp = httplib.HTTPResponse(sock, 1, method="HEAD")
153 resp.begin()
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000154 if resp.read() != "":
155 raise AssertionError, "Did not expect response from HEAD request"
156 resp.close()
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000157
Jeremy Hylton2c178252004-08-07 16:28:14 +0000158
159def test_main(verbose=None):
160 tests = [HeaderTests,]
161 test_support.run_unittest(*tests)
162
Jeremy Hyltonba603192003-01-23 18:02:20 +0000163test()