blob: 48b23600846ae44ddf6415404e5e877d19ca3e3d [file] [log] [blame]
jcgregorio2d66d4f2006-02-07 05:34:14 +00001#!/usr/bin/env python2.4
2"""
3httplib2test
4
5A set of unit tests for httplib2.py.
6
7Requires Python 2.4 or later
8"""
9
10__author__ = "Joe Gregorio (joe@bitworking.org)"
11__copyright__ = "Copyright 2006, Joe Gregorio"
12__contributors__ = []
13__license__ = "MIT"
14__history__ = """ """
15__version__ = "0.1 ($Rev: 118 $)"
16
17
Joe Gregoriob6c90c42011-02-11 01:03:22 -050018import StringIO
19import base64
jcgregoriode8238d2007-03-07 19:08:26 +000020import httplib
21import httplib2
22import os
Joe Gregoriob6c90c42011-02-11 01:03:22 -050023import socket
24import sys
jcgregoriode8238d2007-03-07 19:08:26 +000025import time
Joe Gregoriob6c90c42011-02-11 01:03:22 -050026import unittest
27import urlparse
jcgregorio8421f272006-02-14 18:19:51 +000028
Joe Gregoriob53de9b2011-06-07 15:44:51 -040029try:
30 import ssl
31except ImportError:
32 pass
Joe Gregorio694a8122011-02-13 21:40:09 -050033
jcgregorio8421f272006-02-14 18:19:51 +000034# Python 2.3 support
35if not hasattr(unittest.TestCase, 'assertTrue'):
36 unittest.TestCase.assertTrue = unittest.TestCase.failUnless
37 unittest.TestCase.assertFalse = unittest.TestCase.failIf
38
jcgregorio2d66d4f2006-02-07 05:34:14 +000039# The test resources base uri
40base = 'http://bitworking.org/projects/httplib2/test/'
41#base = 'http://localhost/projects/httplib2/test/'
jcgregorio90fb4a42006-11-17 16:19:47 +000042cacheDirName = ".cache"
jcgregorio2d66d4f2006-02-07 05:34:14 +000043
jcgregoriode8238d2007-03-07 19:08:26 +000044
45class CredentialsTest(unittest.TestCase):
46 def test(self):
47 c = httplib2.Credentials()
48 c.add("joe", "password")
49 self.assertEqual(("joe", "password"), list(c.iter("bitworking.org"))[0])
50 self.assertEqual(("joe", "password"), list(c.iter(""))[0])
51 c.add("fred", "password2", "wellformedweb.org")
52 self.assertEqual(("joe", "password"), list(c.iter("bitworking.org"))[0])
53 self.assertEqual(1, len(list(c.iter("bitworking.org"))))
54 self.assertEqual(2, len(list(c.iter("wellformedweb.org"))))
55 self.assertTrue(("fred", "password2") in list(c.iter("wellformedweb.org")))
56 c.clear()
57 self.assertEqual(0, len(list(c.iter("bitworking.org"))))
58 c.add("fred", "password2", "wellformedweb.org")
59 self.assertTrue(("fred", "password2") in list(c.iter("wellformedweb.org")))
60 self.assertEqual(0, len(list(c.iter("bitworking.org"))))
61 self.assertEqual(0, len(list(c.iter(""))))
62
63
jcgregorio2d66d4f2006-02-07 05:34:14 +000064class ParserTest(unittest.TestCase):
65 def testFromStd66(self):
66 self.assertEqual( ('http', 'example.com', '', None, None ), httplib2.parse_uri("http://example.com"))
67 self.assertEqual( ('https', 'example.com', '', None, None ), httplib2.parse_uri("https://example.com"))
68 self.assertEqual( ('https', 'example.com:8080', '', None, None ), httplib2.parse_uri("https://example.com:8080"))
69 self.assertEqual( ('http', 'example.com', '/', None, None ), httplib2.parse_uri("http://example.com/"))
70 self.assertEqual( ('http', 'example.com', '/path', None, None ), httplib2.parse_uri("http://example.com/path"))
71 self.assertEqual( ('http', 'example.com', '/path', 'a=1&b=2', None ), httplib2.parse_uri("http://example.com/path?a=1&b=2"))
72 self.assertEqual( ('http', 'example.com', '/path', 'a=1&b=2', 'fred' ), httplib2.parse_uri("http://example.com/path?a=1&b=2#fred"))
73 self.assertEqual( ('http', 'example.com', '/path', 'a=1&b=2', 'fred' ), httplib2.parse_uri("http://example.com/path?a=1&b=2#fred"))
74
jcgregorio2d66d4f2006-02-07 05:34:14 +000075
jcgregorioa46fe4e2006-11-16 04:13:45 +000076class UrlNormTest(unittest.TestCase):
77 def test(self):
78 self.assertEqual( "http://example.org/", httplib2.urlnorm("http://example.org")[-1])
79 self.assertEqual( "http://example.org/", httplib2.urlnorm("http://EXAMple.org")[-1])
80 self.assertEqual( "http://example.org/?=b", httplib2.urlnorm("http://EXAMple.org?=b")[-1])
81 self.assertEqual( "http://example.org/mypath?a=b", httplib2.urlnorm("http://EXAMple.org/mypath?a=b")[-1])
82 self.assertEqual( "http://localhost:80/", httplib2.urlnorm("http://localhost:80")[-1])
jcgregoriob4e9ab02006-11-17 15:53:15 +000083 self.assertEqual( httplib2.urlnorm("http://localhost:80/"), httplib2.urlnorm("HTTP://LOCALHOST:80"))
jcgregorio132d28e2007-01-23 16:22:53 +000084 try:
85 httplib2.urlnorm("/")
86 self.fail("Non-absolute URIs should raise an exception")
87 except httplib2.RelativeURIError:
88 pass
jcgregorioa46fe4e2006-11-16 04:13:45 +000089
90class UrlSafenameTest(unittest.TestCase):
91 def test(self):
92 # Test that different URIs end up generating different safe names
93 self.assertEqual( "example.org,fred,a=b,58489f63a7a83c3b7794a6a398ee8b1f", httplib2.safename("http://example.org/fred/?a=b"))
94 self.assertEqual( "example.org,fred,a=b,8c5946d56fec453071f43329ff0be46b", httplib2.safename("http://example.org/fred?/a=b"))
95 self.assertEqual( "www.example.org,fred,a=b,499c44b8d844a011b67ea2c015116968", httplib2.safename("http://www.example.org/fred?/a=b"))
96 self.assertEqual( httplib2.safename(httplib2.urlnorm("http://www")[-1]), httplib2.safename(httplib2.urlnorm("http://WWW")[-1]))
97 self.assertEqual( "www.example.org,fred,a=b,692e843a333484ce0095b070497ab45d", httplib2.safename("https://www.example.org/fred?/a=b"))
98 self.assertNotEqual( httplib2.safename("http://www"), httplib2.safename("https://www"))
99 # Test the max length limits
100 uri = "http://" + ("w" * 200) + ".org"
101 uri2 = "http://" + ("w" * 201) + ".org"
102 self.assertNotEqual( httplib2.safename(uri2), httplib2.safename(uri))
103 # Max length should be 200 + 1 (",") + 32
104 self.assertEqual(233, len(httplib2.safename(uri2)))
105 self.assertEqual(233, len(httplib2.safename(uri)))
106 # Unicode
jcgregoriodebceec2006-12-12 20:26:02 +0000107 if sys.version_info >= (2,3):
108 self.assertEqual( "xn--http,-4y1d.org,fred,a=b,579924c35db315e5a32e3d9963388193", httplib2.safename(u"http://\u2304.org/fred/?a=b"))
jcgregorioa46fe4e2006-11-16 04:13:45 +0000109
jcgregorio14644372007-07-30 14:13:37 +0000110class _MyResponse(StringIO.StringIO):
111 def __init__(self, body, **kwargs):
112 StringIO.StringIO.__init__(self, body)
113 self.headers = kwargs
114
115 def iteritems(self):
116 return self.headers.iteritems()
117
118
119class _MyHTTPConnection(object):
120 "This class is just a mock of httplib.HTTPConnection used for testing"
121
122 def __init__(self, host, port=None, key_file=None, cert_file=None,
joe.gregoriof28536d2007-10-23 14:10:11 +0000123 strict=None, timeout=None, proxy_info=None):
jcgregorio14644372007-07-30 14:13:37 +0000124 self.host = host
125 self.port = port
126 self.timeout = timeout
127 self.log = ""
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400128 self.sock = None
jcgregorio14644372007-07-30 14:13:37 +0000129
130 def set_debuglevel(self, level):
131 pass
132
133 def connect(self):
134 "Connect to a host on a given port."
135 pass
136
137 def close(self):
138 pass
139
140 def request(self, method, request_uri, body, headers):
141 pass
142
143 def getresponse(self):
144 return _MyResponse("the body", status="200")
jcgregorioa46fe4e2006-11-16 04:13:45 +0000145
jcgregorio90fb4a42006-11-17 16:19:47 +0000146
jcgregorio2d66d4f2006-02-07 05:34:14 +0000147class HttpTest(unittest.TestCase):
148 def setUp(self):
jcgregorio7e3608f2006-06-15 13:01:53 +0000149 if os.path.exists(cacheDirName):
150 [os.remove(os.path.join(cacheDirName, file)) for file in os.listdir(cacheDirName)]
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400151
152 if sys.version_info < (2, 6):
153 disable_cert_validation = True
154 else:
155 disable_cert_validation = False
156 self.http = httplib2.Http(
157 cacheDirName,
158 disable_ssl_certificate_validation=disable_cert_validation)
jcgregorio36140b52006-06-13 02:17:52 +0000159 self.http.clear_credentials()
jcgregorio2d66d4f2006-02-07 05:34:14 +0000160
Joe Gregoriof3ee17b2011-02-13 11:59:51 -0500161 def testIPv6NoSSL(self):
162 try:
163 self.http.request("http://[::1]/")
164 except socket.gaierror:
165 self.fail("should get the address family right for IPv6")
166 except socket.error:
167 # Even if IPv6 isn't installed on a machine it should just raise socket.error
168 pass
169
170 def testIPv6SSL(self):
171 try:
172 self.http.request("https://[::1]/")
173 except socket.gaierror:
174 self.fail("should get the address family right for IPv6")
175 except socket.error:
176 # Even if IPv6 isn't installed on a machine it should just raise socket.error
177 pass
178
jcgregorio14644372007-07-30 14:13:37 +0000179 def testConnectionType(self):
joe.gregoriof28536d2007-10-23 14:10:11 +0000180 self.http.force_exception_to_status_code = False
jcgregorio14644372007-07-30 14:13:37 +0000181 response, content = self.http.request("http://bitworking.org", connection_type=_MyHTTPConnection)
182 self.assertEqual(response['content-location'], "http://bitworking.org")
183 self.assertEqual(content, "the body")
184
jcgregorio6a638172007-01-23 16:40:23 +0000185 def testGetUnknownServer(self):
jcgregorio07a9a4a2007-03-08 21:18:39 +0000186 self.http.force_exception_to_status_code = False
jcgregorio6a638172007-01-23 16:40:23 +0000187 try:
188 self.http.request("http://fred.bitworking.org/")
189 self.fail("An httplib2.ServerNotFoundError Exception must be thrown on an unresolvable server.")
190 except httplib2.ServerNotFoundError:
191 pass
192
jcgregorio07a9a4a2007-03-08 21:18:39 +0000193 # Now test with exceptions turned off
194 self.http.force_exception_to_status_code = True
195
196 (response, content) = self.http.request("http://fred.bitworking.org/")
197 self.assertEqual(response['content-type'], 'text/plain')
198 self.assertTrue(content.startswith("Unable to find"))
199 self.assertEqual(response.status, 400)
200
Joe Gregoriob6c90c42011-02-11 01:03:22 -0500201 def testGetConnectionRefused(self):
202 self.http.force_exception_to_status_code = False
203 try:
204 self.http.request("http://localhost:7777/")
205 self.fail("An socket.error exception must be thrown on Connection Refused.")
206 except socket.error:
207 pass
208
209 # Now test with exceptions turned off
210 self.http.force_exception_to_status_code = True
211
212 (response, content) = self.http.request("http://localhost:7777/")
213 self.assertEqual(response['content-type'], 'text/plain')
214 self.assertTrue("Connection refused" in content)
215 self.assertEqual(response.status, 400)
216
jcgregorioa898f8f2006-12-12 17:16:55 +0000217 def testGetIRI(self):
jcgregoriodebceec2006-12-12 20:26:02 +0000218 if sys.version_info >= (2,3):
219 uri = urlparse.urljoin(base, u"reflector/reflector.cgi?d=\N{CYRILLIC CAPITAL LETTER DJE}")
220 (response, content) = self.http.request(uri, "GET")
221 d = self.reflector(content)
222 self.assertTrue(d.has_key('QUERY_STRING'))
223 self.assertTrue(d['QUERY_STRING'].find('%D0%82') > 0)
jcgregorioa898f8f2006-12-12 17:16:55 +0000224
jcgregorio2d66d4f2006-02-07 05:34:14 +0000225 def testGetIsDefaultMethod(self):
226 # Test that GET is the default method
227 uri = urlparse.urljoin(base, "methods/method_reflector.cgi")
jcgregorio36140b52006-06-13 02:17:52 +0000228 (response, content) = self.http.request(uri)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000229 self.assertEqual(response['x-method'], "GET")
230
231 def testDifferentMethods(self):
232 # Test that all methods can be used
233 uri = urlparse.urljoin(base, "methods/method_reflector.cgi")
234 for method in ["GET", "PUT", "DELETE", "POST"]:
jcgregorio36140b52006-06-13 02:17:52 +0000235 (response, content) = self.http.request(uri, method, body=" ")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000236 self.assertEqual(response['x-method'], method)
237
Joe Gregoriob628c0b2009-07-16 12:28:04 -0400238 def testHeadRead(self):
239 # Test that we don't try to read the response of a HEAD request
240 # since httplib blocks response.read() for HEAD requests.
241 # Oddly enough this doesn't appear as a problem when doing HEAD requests
242 # against Apache servers.
243 uri = "http://www.google.com/"
244 (response, content) = self.http.request(uri, "HEAD")
245 self.assertEqual(response.status, 200)
246 self.assertEqual(content, "")
247
jcgregorio2d66d4f2006-02-07 05:34:14 +0000248 def testGetNoCache(self):
249 # Test that can do a GET w/o the cache turned on.
250 http = httplib2.Http()
251 uri = urlparse.urljoin(base, "304/test_etag.txt")
252 (response, content) = http.request(uri, "GET")
253 self.assertEqual(response.status, 200)
jcgregorioa0713ab2006-07-01 05:21:34 +0000254 self.assertEqual(response.previous, None)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000255
Joe Gregorioe202d212009-07-16 14:57:52 -0400256 def testGetOnlyIfCachedCacheHit(self):
257 # Test that can do a GET with cache and 'only-if-cached'
258 uri = urlparse.urljoin(base, "304/test_etag.txt")
259 (response, content) = self.http.request(uri, "GET")
260 (response, content) = self.http.request(uri, "GET", headers={'cache-control': 'only-if-cached'})
261 self.assertEqual(response.fromcache, True)
262 self.assertEqual(response.status, 200)
263
jcgregorioe4ce13e2006-04-02 03:05:08 +0000264 def testGetOnlyIfCachedCacheMiss(self):
265 # Test that can do a GET with no cache with 'only-if-cached'
jcgregorioe4ce13e2006-04-02 03:05:08 +0000266 uri = urlparse.urljoin(base, "304/test_etag.txt")
Joe Gregorioe202d212009-07-16 14:57:52 -0400267 (response, content) = self.http.request(uri, "GET", headers={'cache-control': 'only-if-cached'})
jcgregorioe4ce13e2006-04-02 03:05:08 +0000268 self.assertEqual(response.fromcache, False)
Joe Gregorioe202d212009-07-16 14:57:52 -0400269 self.assertEqual(response.status, 504)
jcgregorioe4ce13e2006-04-02 03:05:08 +0000270
271 def testGetOnlyIfCachedNoCacheAtAll(self):
272 # Test that can do a GET with no cache with 'only-if-cached'
273 # Of course, there might be an intermediary beyond us
274 # that responds to the 'only-if-cached', so this
275 # test can't really be guaranteed to pass.
276 http = httplib2.Http()
277 uri = urlparse.urljoin(base, "304/test_etag.txt")
278 (response, content) = http.request(uri, "GET", headers={'cache-control': 'only-if-cached'})
279 self.assertEqual(response.fromcache, False)
Joe Gregorioe202d212009-07-16 14:57:52 -0400280 self.assertEqual(response.status, 504)
jcgregorioe4ce13e2006-04-02 03:05:08 +0000281
jcgregorio2d66d4f2006-02-07 05:34:14 +0000282 def testUserAgent(self):
283 # Test that we provide a default user-agent
284 uri = urlparse.urljoin(base, "user-agent/test.cgi")
jcgregorio36140b52006-06-13 02:17:52 +0000285 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000286 self.assertEqual(response.status, 200)
287 self.assertTrue(content.startswith("Python-httplib2/"))
288
289 def testUserAgentNonDefault(self):
290 # Test that the default user-agent can be over-ridden
joe.gregoriof28536d2007-10-23 14:10:11 +0000291
jcgregorio2d66d4f2006-02-07 05:34:14 +0000292 uri = urlparse.urljoin(base, "user-agent/test.cgi")
jcgregorio36140b52006-06-13 02:17:52 +0000293 (response, content) = self.http.request(uri, "GET", headers={'User-Agent': 'fred/1.0'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000294 self.assertEqual(response.status, 200)
295 self.assertTrue(content.startswith("fred/1.0"))
296
297 def testGet300WithLocation(self):
298 # Test the we automatically follow 300 redirects if a Location: header is provided
299 uri = urlparse.urljoin(base, "300/with-location-header.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000300 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000301 self.assertEqual(response.status, 200)
302 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000303 self.assertEqual(response.previous.status, 300)
304 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000305
306 # Confirm that the intermediate 300 is not cached
jcgregorio36140b52006-06-13 02:17:52 +0000307 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000308 self.assertEqual(response.status, 200)
309 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000310 self.assertEqual(response.previous.status, 300)
311 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000312
jcgregorio2f1e1422007-05-03 13:17:33 +0000313 def testGet300WithLocationNoRedirect(self):
314 # Test the we automatically follow 300 redirects if a Location: header is provided
315 self.http.follow_redirects = False
316 uri = urlparse.urljoin(base, "300/with-location-header.asis")
317 (response, content) = self.http.request(uri, "GET")
318 self.assertEqual(response.status, 300)
319
jcgregorio2d66d4f2006-02-07 05:34:14 +0000320 def testGet300WithoutLocation(self):
321 # Not giving a Location: header in a 300 response is acceptable
322 # In which case we just return the 300 response
323 uri = urlparse.urljoin(base, "300/without-location-header.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000324 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000325 self.assertEqual(response.status, 300)
326 self.assertTrue(response['content-type'].startswith("text/html"))
jcgregorioa0713ab2006-07-01 05:21:34 +0000327 self.assertEqual(response.previous, None)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000328
329 def testGet301(self):
330 # Test that we automatically follow 301 redirects
331 # and that we cache the 301 response
332 uri = urlparse.urljoin(base, "301/onestep.asis")
jcgregorio8e300b92006-11-07 16:44:35 +0000333 destination = urlparse.urljoin(base, "302/final-destination.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000334 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000335 self.assertEqual(response.status, 200)
jcgregorio772adc82006-11-17 21:52:34 +0000336 self.assertTrue(response.has_key('content-location'))
337 self.assertEqual(response['content-location'], destination)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000338 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000339 self.assertEqual(response.previous.status, 301)
340 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000341
jcgregorio36140b52006-06-13 02:17:52 +0000342 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000343 self.assertEqual(response.status, 200)
jcgregorio772adc82006-11-17 21:52:34 +0000344 self.assertEqual(response['content-location'], destination)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000345 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000346 self.assertEqual(response.previous.status, 301)
347 self.assertEqual(response.previous.fromcache, True)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000348
Joe Gregorio694a8122011-02-13 21:40:09 -0500349 def testHead301(self):
350 # Test that we automatically follow 301 redirects
351 uri = urlparse.urljoin(base, "301/onestep.asis")
352 destination = urlparse.urljoin(base, "302/final-destination.txt")
353 (response, content) = self.http.request(uri, "HEAD")
354 self.assertEqual(response.status, 200)
355 self.assertEqual(response.previous.status, 301)
356 self.assertEqual(response.previous.fromcache, False)
jcgregorio2f1e1422007-05-03 13:17:33 +0000357
358 def testGet301NoRedirect(self):
359 # Test that we automatically follow 301 redirects
360 # and that we cache the 301 response
361 self.http.follow_redirects = False
362 uri = urlparse.urljoin(base, "301/onestep.asis")
363 destination = urlparse.urljoin(base, "302/final-destination.txt")
364 (response, content) = self.http.request(uri, "GET")
365 self.assertEqual(response.status, 301)
366
367
jcgregorio2d66d4f2006-02-07 05:34:14 +0000368 def testGet302(self):
369 # Test that we automatically follow 302 redirects
370 # and that we DO NOT cache the 302 response
371 uri = urlparse.urljoin(base, "302/onestep.asis")
jcgregorio8e300b92006-11-07 16:44:35 +0000372 destination = urlparse.urljoin(base, "302/final-destination.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000373 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000374 self.assertEqual(response.status, 200)
jcgregorio772adc82006-11-17 21:52:34 +0000375 self.assertEqual(response['content-location'], destination)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000376 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000377 self.assertEqual(response.previous.status, 302)
378 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000379
380 uri = urlparse.urljoin(base, "302/onestep.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000381 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000382 self.assertEqual(response.status, 200)
383 self.assertEqual(response.fromcache, True)
jcgregorio772adc82006-11-17 21:52:34 +0000384 self.assertEqual(response['content-location'], destination)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000385 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000386 self.assertEqual(response.previous.status, 302)
387 self.assertEqual(response.previous.fromcache, False)
jcgregorio772adc82006-11-17 21:52:34 +0000388 self.assertEqual(response.previous['content-location'], uri)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000389
390 uri = urlparse.urljoin(base, "302/twostep.asis")
391
jcgregorio36140b52006-06-13 02:17:52 +0000392 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000393 self.assertEqual(response.status, 200)
394 self.assertEqual(response.fromcache, True)
395 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000396 self.assertEqual(response.previous.status, 302)
397 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000398
399 def testGet302RedirectionLimit(self):
400 # Test that we can set a lower redirection limit
401 # and that we raise an exception when we exceed
402 # that limit.
jcgregorio07a9a4a2007-03-08 21:18:39 +0000403 self.http.force_exception_to_status_code = False
404
jcgregorio2d66d4f2006-02-07 05:34:14 +0000405 uri = urlparse.urljoin(base, "302/twostep.asis")
406 try:
jcgregorio36140b52006-06-13 02:17:52 +0000407 (response, content) = self.http.request(uri, "GET", redirections = 1)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000408 self.fail("This should not happen")
409 except httplib2.RedirectLimit:
410 pass
411 except Exception, e:
412 self.fail("Threw wrong kind of exception ")
413
jcgregorio07a9a4a2007-03-08 21:18:39 +0000414 # Re-run the test with out the exceptions
415 self.http.force_exception_to_status_code = True
416
417 (response, content) = self.http.request(uri, "GET", redirections = 1)
418 self.assertEqual(response.status, 500)
419 self.assertTrue(response.reason.startswith("Redirected more"))
420 self.assertEqual("302", response['status'])
421 self.assertTrue(content.startswith("<html>"))
422 self.assertTrue(response.previous != None)
423
jcgregorio2d66d4f2006-02-07 05:34:14 +0000424 def testGet302NoLocation(self):
425 # Test that we throw an exception when we get
426 # a 302 with no Location: header.
jcgregorio07a9a4a2007-03-08 21:18:39 +0000427 self.http.force_exception_to_status_code = False
jcgregorio2d66d4f2006-02-07 05:34:14 +0000428 uri = urlparse.urljoin(base, "302/no-location.asis")
429 try:
jcgregorio36140b52006-06-13 02:17:52 +0000430 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000431 self.fail("Should never reach here")
432 except httplib2.RedirectMissingLocation:
433 pass
434 except Exception, e:
435 self.fail("Threw wrong kind of exception ")
436
jcgregorio07a9a4a2007-03-08 21:18:39 +0000437 # Re-run the test with out the exceptions
438 self.http.force_exception_to_status_code = True
439
440 (response, content) = self.http.request(uri, "GET")
441 self.assertEqual(response.status, 500)
442 self.assertTrue(response.reason.startswith("Redirected but"))
443 self.assertEqual("302", response['status'])
444 self.assertTrue(content.startswith("This is content"))
Joe Gregorio84e33252011-05-03 09:09:13 -0400445
Joe Gregorioac335ff2011-11-14 12:29:03 -0500446 def testGet301ViaHttps(self):
447 # Google always redirects to https://www.google.com
448 (response, content) = self.http.request("https://code.google.com/apis/", "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000449 self.assertEqual(200, response.status)
Joe Gregorioac335ff2011-11-14 12:29:03 -0500450 self.assertEqual(301, response.previous.status)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000451
452 def testGetViaHttps(self):
453 # Test that we can handle HTTPS
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400454 (response, content) = self.http.request("https://www.google.com/adsense/", "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000455 self.assertEqual(200, response.status)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000456
457 def testGetViaHttpsSpecViolationOnLocation(self):
458 # Test that we follow redirects through HTTPS
459 # even if they violate the spec by including
460 # a relative Location: header instead of an
461 # absolute one.
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400462 (response, content) = self.http.request("https://www.google.com/adsense", "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000463 self.assertEqual(200, response.status)
jcgregorioa0713ab2006-07-01 05:21:34 +0000464 self.assertNotEqual(None, response.previous)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000465
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400466 def testSslCertValidation(self):
467 if sys.version_info >= (2, 6):
468 # Test that we get an ssl.SSLError when specifying a non-existent CA
469 # certs file.
470 http = httplib2.Http(ca_certs='/nosuchfile')
471 self.assertRaises(ssl.SSLError,
472 http.request, "https://www.google.com/", "GET")
473
474 # Test that we get a SSLHandshakeError if we try to access
475 # https;//www.google.com, using a CA cert file that doesn't contain
476 # the CA Gogole uses (i.e., simulating a cert that's not signed by a
477 # trusted CA).
478 other_ca_certs = os.path.join(
479 os.path.dirname(os.path.abspath(httplib2.__file__ )),
480 "test", "other_cacerts.txt")
481 http = httplib2.Http(ca_certs=other_ca_certs)
482 self.assertRaises(httplib2.SSLHandshakeError,
483 http.request, "https://www.google.com/", "GET")
484
Joe Gregorioc69dc782011-06-23 08:56:59 -0400485 def testSslCertValidationDoubleDots(self):
486 if sys.version_info >= (2, 6):
487 # Test that we get match a double dot cert
488 try:
489 self.http.request("https://1.www.appspot.com/", "GET")
490 except httplib2.CertificateHostnameMismatch:
491 self.fail('cert with *.*.appspot.com should not raise an exception.')
492
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400493 def testSslHostnameValidation(self):
494 if sys.version_info >= (2, 6):
495 # The SSL server at google.com:443 returns a certificate for
496 # 'www.google.com', which results in a host name mismatch.
497 # Note that this test only works because the ssl module and httplib2
498 # do not support SNI; for requests specifying a server name of
499 # 'google.com' via SNI, a matching cert would be returned.
500 self.assertRaises(httplib2.CertificateHostnameMismatch,
501 self.http.request, "https://google.com/", "GET")
502
503 def testSslCertValidationWithoutSslModuleFails(self):
504 if sys.version_info < (2, 6):
505 http = httplib2.Http(disable_ssl_certificate_validation=False)
506 self.assertRaises(httplib2.CertificateValidationUnsupported,
507 http.request, "https://www.google.com/", "GET")
jcgregoriode8238d2007-03-07 19:08:26 +0000508
509 def testGetViaHttpsKeyCert(self):
jcgregorio2f1e1422007-05-03 13:17:33 +0000510 # At this point I can only test
511 # that the key and cert files are passed in
512 # correctly to httplib. It would be nice to have
513 # a real https endpoint to test against.
Joe Gregoriob53de9b2011-06-07 15:44:51 -0400514
515 # bitworking.org presents an certificate for a non-matching host
516 # (*.webfaction.com), so we need to disable cert checking for this test.
517 http = httplib2.Http(timeout=2, disable_ssl_certificate_validation=True)
jcgregoriode8238d2007-03-07 19:08:26 +0000518
519 http.add_certificate("akeyfile", "acertfile", "bitworking.org")
520 try:
521 (response, content) = http.request("https://bitworking.org", "GET")
522 except:
523 pass
524 self.assertEqual(http.connections["https:bitworking.org"].key_file, "akeyfile")
525 self.assertEqual(http.connections["https:bitworking.org"].cert_file, "acertfile")
526
jcgregorio2f1e1422007-05-03 13:17:33 +0000527 try:
528 (response, content) = http.request("https://notthere.bitworking.org", "GET")
529 except:
530 pass
531 self.assertEqual(http.connections["https:notthere.bitworking.org"].key_file, None)
532 self.assertEqual(http.connections["https:notthere.bitworking.org"].cert_file, None)
533
534
535
jcgregoriode8238d2007-03-07 19:08:26 +0000536
jcgregorio2d66d4f2006-02-07 05:34:14 +0000537 def testGet303(self):
538 # Do a follow-up GET on a Location: header
539 # returned from a POST that gave a 303.
540 uri = urlparse.urljoin(base, "303/303.cgi")
jcgregorio36140b52006-06-13 02:17:52 +0000541 (response, content) = self.http.request(uri, "POST", " ")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000542 self.assertEqual(response.status, 200)
543 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000544 self.assertEqual(response.previous.status, 303)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000545
jcgregorio2f1e1422007-05-03 13:17:33 +0000546 def testGet303NoRedirect(self):
547 # Do a follow-up GET on a Location: header
548 # returned from a POST that gave a 303.
549 self.http.follow_redirects = False
550 uri = urlparse.urljoin(base, "303/303.cgi")
551 (response, content) = self.http.request(uri, "POST", " ")
552 self.assertEqual(response.status, 303)
553
jcgregorio2d66d4f2006-02-07 05:34:14 +0000554 def test303ForDifferentMethods(self):
555 # Test that all methods can be used
556 uri = urlparse.urljoin(base, "303/redirect-to-reflector.cgi")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000557 for (method, method_on_303) in [("PUT", "GET"), ("DELETE", "GET"), ("POST", "GET"), ("GET", "GET"), ("HEAD", "GET")]:
jcgregorio36140b52006-06-13 02:17:52 +0000558 (response, content) = self.http.request(uri, method, body=" ")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000559 self.assertEqual(response['x-method'], method_on_303)
560
561 def testGet304(self):
562 # Test that we use ETags properly to validate our cache
563 uri = urlparse.urljoin(base, "304/test_etag.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000564 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000565 self.assertNotEqual(response['etag'], "")
566
jcgregorio36140b52006-06-13 02:17:52 +0000567 (response, content) = self.http.request(uri, "GET")
568 (response, content) = self.http.request(uri, "GET", headers = {'cache-control': 'must-revalidate'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000569 self.assertEqual(response.status, 200)
570 self.assertEqual(response.fromcache, True)
571
jcgregorio90fb4a42006-11-17 16:19:47 +0000572 cache_file_name = os.path.join(cacheDirName, httplib2.safename(httplib2.urlnorm(uri)[-1]))
573 f = open(cache_file_name, "r")
574 status_line = f.readline()
575 f.close()
576
577 self.assertTrue(status_line.startswith("status:"))
578
jcgregorio36140b52006-06-13 02:17:52 +0000579 (response, content) = self.http.request(uri, "HEAD")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000580 self.assertEqual(response.status, 200)
581 self.assertEqual(response.fromcache, True)
582
jcgregorio36140b52006-06-13 02:17:52 +0000583 (response, content) = self.http.request(uri, "GET", headers = {'range': 'bytes=0-0'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000584 self.assertEqual(response.status, 206)
585 self.assertEqual(response.fromcache, False)
586
jcgregorio25185622006-10-28 05:12:34 +0000587 def testGetIgnoreEtag(self):
588 # Test that we can forcibly ignore ETags
589 uri = urlparse.urljoin(base, "reflector/reflector.cgi")
590 (response, content) = self.http.request(uri, "GET")
591 self.assertNotEqual(response['etag'], "")
592
593 (response, content) = self.http.request(uri, "GET", headers = {'cache-control': 'max-age=0'})
594 d = self.reflector(content)
595 self.assertTrue(d.has_key('HTTP_IF_NONE_MATCH'))
596
597 self.http.ignore_etag = True
598 (response, content) = self.http.request(uri, "GET", headers = {'cache-control': 'max-age=0'})
599 d = self.reflector(content)
600 self.assertEqual(response.fromcache, False)
601 self.assertFalse(d.has_key('HTTP_IF_NONE_MATCH'))
602
jcgregorio4b145e82007-01-18 19:46:34 +0000603 def testOverrideEtag(self):
604 # Test that we can forcibly ignore ETags
605 uri = urlparse.urljoin(base, "reflector/reflector.cgi")
606 (response, content) = self.http.request(uri, "GET")
607 self.assertNotEqual(response['etag'], "")
608
609 (response, content) = self.http.request(uri, "GET", headers = {'cache-control': 'max-age=0'})
610 d = self.reflector(content)
611 self.assertTrue(d.has_key('HTTP_IF_NONE_MATCH'))
612 self.assertNotEqual(d['HTTP_IF_NONE_MATCH'], "fred")
613
pilgrim00a352e2009-05-29 04:04:44 +0000614 (response, content) = self.http.request(uri, "GET", headers = {'cache-control': 'max-age=0', 'if-none-match': 'fred'})
jcgregorio4b145e82007-01-18 19:46:34 +0000615 d = self.reflector(content)
616 self.assertTrue(d.has_key('HTTP_IF_NONE_MATCH'))
617 self.assertEqual(d['HTTP_IF_NONE_MATCH'], "fred")
jcgregorio25185622006-10-28 05:12:34 +0000618
pilgrim00a352e2009-05-29 04:04:44 +0000619#MAP-commented this out because it consistently fails
620# def testGet304EndToEnd(self):
621# # Test that end to end headers get overwritten in the cache
622# uri = urlparse.urljoin(base, "304/end2end.cgi")
623# (response, content) = self.http.request(uri, "GET")
624# self.assertNotEqual(response['etag'], "")
625# old_date = response['date']
626# time.sleep(2)
627#
628# (response, content) = self.http.request(uri, "GET", headers = {'Cache-Control': 'max-age=0'})
629# # The response should be from the cache, but the Date: header should be updated.
630# new_date = response['date']
631# self.assertNotEqual(new_date, old_date)
632# self.assertEqual(response.status, 200)
633# self.assertEqual(response.fromcache, True)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000634
635 def testGet304LastModified(self):
636 # Test that we can still handle a 304
637 # by only using the last-modified cache validator.
638 uri = urlparse.urljoin(base, "304/last-modified-only/last-modified-only.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000639 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000640
641 self.assertNotEqual(response['last-modified'], "")
jcgregorio36140b52006-06-13 02:17:52 +0000642 (response, content) = self.http.request(uri, "GET")
643 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000644 self.assertEqual(response.status, 200)
645 self.assertEqual(response.fromcache, True)
646
647 def testGet307(self):
648 # Test that we do follow 307 redirects but
649 # do not cache the 307
650 uri = urlparse.urljoin(base, "307/onestep.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000651 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000652 self.assertEqual(response.status, 200)
653 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000654 self.assertEqual(response.previous.status, 307)
655 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000656
jcgregorio36140b52006-06-13 02:17:52 +0000657 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000658 self.assertEqual(response.status, 200)
659 self.assertEqual(response.fromcache, True)
660 self.assertEqual(content, "This is the final destination.\n")
jcgregorioa0713ab2006-07-01 05:21:34 +0000661 self.assertEqual(response.previous.status, 307)
662 self.assertEqual(response.previous.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000663
664 def testGet410(self):
665 # Test that we pass 410's through
666 uri = urlparse.urljoin(base, "410/410.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000667 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000668 self.assertEqual(response.status, 410)
669
chris dent89f15142009-12-24 14:02:57 -0600670 def testVaryHeaderSimple(self):
671 """
672 RFC 2616 13.6
673 When the cache receives a subsequent request whose Request-URI
674 specifies one or more cache entries including a Vary header field,
675 the cache MUST NOT use such a cache entry to construct a response
676 to the new request unless all of the selecting request-headers
677 present in the new request match the corresponding stored
678 request-headers in the original request.
679 """
680 # test that the vary header is sent
681 uri = urlparse.urljoin(base, "vary/accept.asis")
682 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/plain'})
683 self.assertEqual(response.status, 200)
684 self.assertTrue(response.has_key('vary'))
685
686 # get the resource again, from the cache since accept header in this
687 # request is the same as the request
688 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/plain'})
689 self.assertEqual(response.status, 200)
690 self.assertEqual(response.fromcache, True, msg="Should be from cache")
691
692 # get the resource again, not from cache since Accept headers does not match
693 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/html'})
694 self.assertEqual(response.status, 200)
695 self.assertEqual(response.fromcache, False, msg="Should not be from cache")
696
697 # get the resource again, without any Accept header, so again no match
698 (response, content) = self.http.request(uri, "GET")
699 self.assertEqual(response.status, 200)
700 self.assertEqual(response.fromcache, False, msg="Should not be from cache")
701
702 def testNoVary(self):
703 # when there is no vary, a different Accept header (e.g.) should not
704 # impact if the cache is used
705 # test that the vary header is not sent
706 uri = urlparse.urljoin(base, "vary/no-vary.asis")
707 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/plain'})
708 self.assertEqual(response.status, 200)
709 self.assertFalse(response.has_key('vary'))
710
711 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/plain'})
712 self.assertEqual(response.status, 200)
713 self.assertEqual(response.fromcache, True, msg="Should be from cache")
714
715 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/html'})
716 self.assertEqual(response.status, 200)
717 self.assertEqual(response.fromcache, True, msg="Should be from cache")
718
719 def testVaryHeaderDouble(self):
720 uri = urlparse.urljoin(base, "vary/accept-double.asis")
721 (response, content) = self.http.request(uri, "GET", headers={
722 'Accept': 'text/plain', 'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7'})
723 self.assertEqual(response.status, 200)
724 self.assertTrue(response.has_key('vary'))
725
726 # we are from cache
727 (response, content) = self.http.request(uri, "GET", headers={
728 'Accept': 'text/plain', 'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7'})
729 self.assertEqual(response.fromcache, True, msg="Should be from cache")
730
731 (response, content) = self.http.request(uri, "GET", headers={'Accept': 'text/plain'})
732 self.assertEqual(response.status, 200)
733 self.assertEqual(response.fromcache, False)
734
735 # get the resource again, not from cache, varied headers don't match exact
736 (response, content) = self.http.request(uri, "GET", headers={'Accept-Language': 'da'})
737 self.assertEqual(response.status, 200)
738 self.assertEqual(response.fromcache, False, msg="Should not be from cache")
739
jcgregorio88ef89b2010-05-13 23:42:11 -0400740 def testVaryUnusedHeader(self):
741 # A header's value is not considered to vary if it's not used at all.
742 uri = urlparse.urljoin(base, "vary/unused-header.asis")
743 (response, content) = self.http.request(uri, "GET", headers={
744 'Accept': 'text/plain'})
745 self.assertEqual(response.status, 200)
746 self.assertTrue(response.has_key('vary'))
747
748 # we are from cache
749 (response, content) = self.http.request(uri, "GET", headers={
750 'Accept': 'text/plain',})
751 self.assertEqual(response.fromcache, True, msg="Should be from cache")
752
chris dent89f15142009-12-24 14:02:57 -0600753
joe.gregorio0d4a2b82007-10-23 14:28:35 +0000754 def testHeadGZip(self):
755 # Test that we don't try to decompress a HEAD response
756 uri = urlparse.urljoin(base, "gzip/final-destination.txt")
757 (response, content) = self.http.request(uri, "HEAD")
758 self.assertEqual(response.status, 200)
759 self.assertNotEqual(int(response['content-length']), 0)
760 self.assertEqual(content, "")
761
jcgregorio2d66d4f2006-02-07 05:34:14 +0000762 def testGetGZip(self):
763 # Test that we support gzip compression
764 uri = urlparse.urljoin(base, "gzip/final-destination.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000765 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000766 self.assertEqual(response.status, 200)
jcgregorio90fb4a42006-11-17 16:19:47 +0000767 self.assertFalse(response.has_key('content-encoding'))
joe.gregorio8b6d2312007-12-16 05:42:07 +0000768 self.assertTrue(response.has_key('-content-encoding'))
jcgregorio153f5882006-11-06 03:33:24 +0000769 self.assertEqual(int(response['content-length']), len("This is the final destination.\n"))
jcgregorio2d66d4f2006-02-07 05:34:14 +0000770 self.assertEqual(content, "This is the final destination.\n")
771
Joe Gregoriod1137c52011-02-13 19:27:35 -0500772 def testPostAndGZipResponse(self):
773 uri = urlparse.urljoin(base, "gzip/post.cgi")
774 (response, content) = self.http.request(uri, "POST", body=" ")
775 self.assertEqual(response.status, 200)
776 self.assertFalse(response.has_key('content-encoding'))
777 self.assertTrue(response.has_key('-content-encoding'))
778
jcgregorio2d66d4f2006-02-07 05:34:14 +0000779 def testGetGZipFailure(self):
780 # Test that we raise a good exception when the gzip fails
jcgregorio07a9a4a2007-03-08 21:18:39 +0000781 self.http.force_exception_to_status_code = False
jcgregorio2d66d4f2006-02-07 05:34:14 +0000782 uri = urlparse.urljoin(base, "gzip/failed-compression.asis")
783 try:
jcgregorio36140b52006-06-13 02:17:52 +0000784 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000785 self.fail("Should never reach here")
786 except httplib2.FailedToDecompressContent:
787 pass
788 except Exception:
789 self.fail("Threw wrong kind of exception")
790
jcgregorio07a9a4a2007-03-08 21:18:39 +0000791 # Re-run the test with out the exceptions
792 self.http.force_exception_to_status_code = True
793
794 (response, content) = self.http.request(uri, "GET")
795 self.assertEqual(response.status, 500)
796 self.assertTrue(response.reason.startswith("Content purported"))
797
798 def testTimeout(self):
jcgregoriob2697912007-03-09 02:23:47 +0000799 self.http.force_exception_to_status_code = True
jcgregorio07a9a4a2007-03-08 21:18:39 +0000800 uri = urlparse.urljoin(base, "timeout/timeout.cgi")
801 try:
802 import socket
803 socket.setdefaulttimeout(1)
804 except:
805 # Don't run the test if we can't set the timeout
806 return
807 (response, content) = self.http.request(uri)
808 self.assertEqual(response.status, 408)
809 self.assertTrue(response.reason.startswith("Request Timeout"))
810 self.assertTrue(content.startswith("Request Timeout"))
811
jcgregoriob2697912007-03-09 02:23:47 +0000812 def testIndividualTimeout(self):
jcgregoriob2697912007-03-09 02:23:47 +0000813 uri = urlparse.urljoin(base, "timeout/timeout.cgi")
814 http = httplib2.Http(timeout=1)
joe.gregoriof28536d2007-10-23 14:10:11 +0000815 http.force_exception_to_status_code = True
jcgregoriob2697912007-03-09 02:23:47 +0000816
817 (response, content) = http.request(uri)
818 self.assertEqual(response.status, 408)
819 self.assertTrue(response.reason.startswith("Request Timeout"))
820 self.assertTrue(content.startswith("Request Timeout"))
821
jcgregorio07a9a4a2007-03-08 21:18:39 +0000822
Joe Gregorio1a7609f2009-07-16 10:59:44 -0400823 def testHTTPSInitTimeout(self):
824 c = httplib2.HTTPSConnectionWithTimeout('localhost', 80, timeout=47)
825 self.assertEqual(47, c.timeout)
826
jcgregorio2d66d4f2006-02-07 05:34:14 +0000827 def testGetDeflate(self):
828 # Test that we support deflate compression
829 uri = urlparse.urljoin(base, "deflate/deflated.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000830 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000831 self.assertEqual(response.status, 200)
jcgregorio90fb4a42006-11-17 16:19:47 +0000832 self.assertFalse(response.has_key('content-encoding'))
jcgregorio153f5882006-11-06 03:33:24 +0000833 self.assertEqual(int(response['content-length']), len("This is the final destination."))
jcgregorio2d66d4f2006-02-07 05:34:14 +0000834 self.assertEqual(content, "This is the final destination.")
835
836 def testGetDeflateFailure(self):
837 # Test that we raise a good exception when the deflate fails
jcgregorio07a9a4a2007-03-08 21:18:39 +0000838 self.http.force_exception_to_status_code = False
839
jcgregorio2d66d4f2006-02-07 05:34:14 +0000840 uri = urlparse.urljoin(base, "deflate/failed-compression.asis")
841 try:
jcgregorio36140b52006-06-13 02:17:52 +0000842 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000843 self.fail("Should never reach here")
844 except httplib2.FailedToDecompressContent:
845 pass
846 except Exception:
847 self.fail("Threw wrong kind of exception")
848
jcgregorio07a9a4a2007-03-08 21:18:39 +0000849 # Re-run the test with out the exceptions
850 self.http.force_exception_to_status_code = True
851
852 (response, content) = self.http.request(uri, "GET")
853 self.assertEqual(response.status, 500)
854 self.assertTrue(response.reason.startswith("Content purported"))
855
jcgregorio2d66d4f2006-02-07 05:34:14 +0000856 def testGetDuplicateHeaders(self):
857 # Test that duplicate headers get concatenated via ','
858 uri = urlparse.urljoin(base, "duplicate-headers/multilink.asis")
jcgregorio36140b52006-06-13 02:17:52 +0000859 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000860 self.assertEqual(response.status, 200)
861 self.assertEqual(content, "This is content\n")
862 self.assertEqual(response['link'].split(",")[0], '<http://bitworking.org>; rel="home"; title="BitWorking"')
863
864 def testGetCacheControlNoCache(self):
865 # Test Cache-Control: no-cache on requests
866 uri = urlparse.urljoin(base, "304/test_etag.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000867 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000868 self.assertNotEqual(response['etag'], "")
jcgregorio36140b52006-06-13 02:17:52 +0000869 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000870 self.assertEqual(response.status, 200)
871 self.assertEqual(response.fromcache, True)
872
jcgregorio36140b52006-06-13 02:17:52 +0000873 (response, content) = self.http.request(uri, "GET", headers={'Cache-Control': 'no-cache'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000874 self.assertEqual(response.status, 200)
875 self.assertEqual(response.fromcache, False)
876
877 def testGetCacheControlPragmaNoCache(self):
878 # Test Pragma: no-cache on requests
879 uri = urlparse.urljoin(base, "304/test_etag.txt")
jcgregorio36140b52006-06-13 02:17:52 +0000880 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000881 self.assertNotEqual(response['etag'], "")
jcgregorio36140b52006-06-13 02:17:52 +0000882 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000883 self.assertEqual(response.status, 200)
884 self.assertEqual(response.fromcache, True)
885
jcgregorio36140b52006-06-13 02:17:52 +0000886 (response, content) = self.http.request(uri, "GET", headers={'Pragma': 'no-cache'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000887 self.assertEqual(response.status, 200)
888 self.assertEqual(response.fromcache, False)
889
890 def testGetCacheControlNoStoreRequest(self):
891 # A no-store request means that the response should not be stored.
892 uri = urlparse.urljoin(base, "304/test_etag.txt")
893
jcgregorio36140b52006-06-13 02:17:52 +0000894 (response, content) = self.http.request(uri, "GET", headers={'Cache-Control': 'no-store'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000895 self.assertEqual(response.status, 200)
896 self.assertEqual(response.fromcache, False)
897
jcgregorio36140b52006-06-13 02:17:52 +0000898 (response, content) = self.http.request(uri, "GET", headers={'Cache-Control': 'no-store'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000899 self.assertEqual(response.status, 200)
900 self.assertEqual(response.fromcache, False)
901
902 def testGetCacheControlNoStoreResponse(self):
903 # A no-store response means that the response should not be stored.
904 uri = urlparse.urljoin(base, "no-store/no-store.asis")
905
jcgregorio36140b52006-06-13 02:17:52 +0000906 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000907 self.assertEqual(response.status, 200)
908 self.assertEqual(response.fromcache, False)
909
jcgregorio36140b52006-06-13 02:17:52 +0000910 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000911 self.assertEqual(response.status, 200)
912 self.assertEqual(response.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000913
914 def testGetCacheControlNoCacheNoStoreRequest(self):
915 # Test that a no-store, no-cache clears the entry from the cache
916 # even if it was cached previously.
917 uri = urlparse.urljoin(base, "304/test_etag.txt")
918
jcgregorio36140b52006-06-13 02:17:52 +0000919 (response, content) = self.http.request(uri, "GET")
920 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000921 self.assertEqual(response.fromcache, True)
jcgregorio36140b52006-06-13 02:17:52 +0000922 (response, content) = self.http.request(uri, "GET", headers={'Cache-Control': 'no-store, no-cache'})
923 (response, content) = self.http.request(uri, "GET", headers={'Cache-Control': 'no-store, no-cache'})
jcgregorio2d66d4f2006-02-07 05:34:14 +0000924 self.assertEqual(response.status, 200)
925 self.assertEqual(response.fromcache, False)
jcgregorio2d66d4f2006-02-07 05:34:14 +0000926
927 def testUpdateInvalidatesCache(self):
928 # Test that calling PUT or DELETE on a
929 # URI that is cache invalidates that cache.
930 uri = urlparse.urljoin(base, "304/test_etag.txt")
931
jcgregorio36140b52006-06-13 02:17:52 +0000932 (response, content) = self.http.request(uri, "GET")
933 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000934 self.assertEqual(response.fromcache, True)
jcgregorio36140b52006-06-13 02:17:52 +0000935 (response, content) = self.http.request(uri, "DELETE")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000936 self.assertEqual(response.status, 405)
937
jcgregorio36140b52006-06-13 02:17:52 +0000938 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000939 self.assertEqual(response.fromcache, False)
940
941 def testUpdateUsesCachedETag(self):
Joe Gregoriobd682082011-05-24 14:06:09 -0400942 # Test that we natively support http://www.w3.org/1999/04/Editing/
jcgregorio2d66d4f2006-02-07 05:34:14 +0000943 uri = urlparse.urljoin(base, "conditional-updates/test.cgi")
944
jcgregorio36140b52006-06-13 02:17:52 +0000945 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000946 self.assertEqual(response.status, 200)
947 self.assertEqual(response.fromcache, False)
jcgregorio36140b52006-06-13 02:17:52 +0000948 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000949 self.assertEqual(response.status, 200)
950 self.assertEqual(response.fromcache, True)
Joe Gregoriocd868102009-09-29 17:09:16 -0400951 (response, content) = self.http.request(uri, "PUT", body="foo")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000952 self.assertEqual(response.status, 200)
Joe Gregoriocd868102009-09-29 17:09:16 -0400953 (response, content) = self.http.request(uri, "PUT", body="foo")
jcgregorio2d66d4f2006-02-07 05:34:14 +0000954 self.assertEqual(response.status, 412)
955
Joe Gregoriobd682082011-05-24 14:06:09 -0400956 def testUpdatePatchUsesCachedETag(self):
957 # Test that we natively support http://www.w3.org/1999/04/Editing/
958 uri = urlparse.urljoin(base, "conditional-updates/test.cgi")
959
960 (response, content) = self.http.request(uri, "GET")
961 self.assertEqual(response.status, 200)
962 self.assertEqual(response.fromcache, False)
963 (response, content) = self.http.request(uri, "GET")
964 self.assertEqual(response.status, 200)
965 self.assertEqual(response.fromcache, True)
966 (response, content) = self.http.request(uri, "PATCH", body="foo")
967 self.assertEqual(response.status, 200)
968 (response, content) = self.http.request(uri, "PATCH", body="foo")
969 self.assertEqual(response.status, 412)
970
971
joe.gregorio700f04d2008-09-06 04:46:32 +0000972 def testUpdateUsesCachedETagAndOCMethod(self):
973 # Test that we natively support http://www.w3.org/1999/04/Editing/
974 uri = urlparse.urljoin(base, "conditional-updates/test.cgi")
975
976 (response, content) = self.http.request(uri, "GET")
977 self.assertEqual(response.status, 200)
978 self.assertEqual(response.fromcache, False)
979 (response, content) = self.http.request(uri, "GET")
980 self.assertEqual(response.status, 200)
981 self.assertEqual(response.fromcache, True)
982 self.http.optimistic_concurrency_methods.append("DELETE")
983 (response, content) = self.http.request(uri, "DELETE")
984 self.assertEqual(response.status, 200)
985
986
jcgregorio4b145e82007-01-18 19:46:34 +0000987 def testUpdateUsesCachedETagOverridden(self):
988 # Test that we natively support http://www.w3.org/1999/04/Editing/
989 uri = urlparse.urljoin(base, "conditional-updates/test.cgi")
990
991 (response, content) = self.http.request(uri, "GET")
992 self.assertEqual(response.status, 200)
993 self.assertEqual(response.fromcache, False)
994 (response, content) = self.http.request(uri, "GET")
995 self.assertEqual(response.status, 200)
996 self.assertEqual(response.fromcache, True)
Joe Gregoriocd868102009-09-29 17:09:16 -0400997 (response, content) = self.http.request(uri, "PUT", body="foo", headers={'if-match': 'fred'})
jcgregorio4b145e82007-01-18 19:46:34 +0000998 self.assertEqual(response.status, 412)
999
jcgregorio2d66d4f2006-02-07 05:34:14 +00001000 def testBasicAuth(self):
1001 # Test Basic Authentication
1002 uri = urlparse.urljoin(base, "basic/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001003 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001004 self.assertEqual(response.status, 401)
1005
1006 uri = urlparse.urljoin(base, "basic/")
jcgregorio36140b52006-06-13 02:17:52 +00001007 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001008 self.assertEqual(response.status, 401)
1009
jcgregorio36140b52006-06-13 02:17:52 +00001010 self.http.add_credentials('joe', 'password')
1011 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001012 self.assertEqual(response.status, 200)
1013
1014 uri = urlparse.urljoin(base, "basic/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001015 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001016 self.assertEqual(response.status, 200)
1017
jcgregoriode8238d2007-03-07 19:08:26 +00001018 def testBasicAuthWithDomain(self):
1019 # Test Basic Authentication
1020 uri = urlparse.urljoin(base, "basic/file.txt")
1021 (response, content) = self.http.request(uri, "GET")
1022 self.assertEqual(response.status, 401)
1023
1024 uri = urlparse.urljoin(base, "basic/")
1025 (response, content) = self.http.request(uri, "GET")
1026 self.assertEqual(response.status, 401)
1027
1028 self.http.add_credentials('joe', 'password', "example.org")
1029 (response, content) = self.http.request(uri, "GET")
1030 self.assertEqual(response.status, 401)
1031
1032 uri = urlparse.urljoin(base, "basic/file.txt")
1033 (response, content) = self.http.request(uri, "GET")
1034 self.assertEqual(response.status, 401)
1035
1036 domain = urlparse.urlparse(base)[1]
1037 self.http.add_credentials('joe', 'password', domain)
1038 (response, content) = self.http.request(uri, "GET")
1039 self.assertEqual(response.status, 200)
1040
1041 uri = urlparse.urljoin(base, "basic/file.txt")
1042 (response, content) = self.http.request(uri, "GET")
1043 self.assertEqual(response.status, 200)
1044
1045
1046
1047
1048
1049
jcgregorio2d66d4f2006-02-07 05:34:14 +00001050 def testBasicAuthTwoDifferentCredentials(self):
jcgregorioadbb4f82006-05-19 15:17:42 +00001051 # Test Basic Authentication with multiple sets of credentials
jcgregorio2d66d4f2006-02-07 05:34:14 +00001052 uri = urlparse.urljoin(base, "basic2/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001053 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001054 self.assertEqual(response.status, 401)
1055
1056 uri = urlparse.urljoin(base, "basic2/")
jcgregorio36140b52006-06-13 02:17:52 +00001057 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001058 self.assertEqual(response.status, 401)
1059
jcgregorio36140b52006-06-13 02:17:52 +00001060 self.http.add_credentials('fred', 'barney')
1061 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001062 self.assertEqual(response.status, 200)
1063
1064 uri = urlparse.urljoin(base, "basic2/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001065 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001066 self.assertEqual(response.status, 200)
1067
1068 def testBasicAuthNested(self):
1069 # Test Basic Authentication with resources
1070 # that are nested
1071 uri = urlparse.urljoin(base, "basic-nested/")
jcgregorio36140b52006-06-13 02:17:52 +00001072 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001073 self.assertEqual(response.status, 401)
1074
1075 uri = urlparse.urljoin(base, "basic-nested/subdir")
jcgregorio36140b52006-06-13 02:17:52 +00001076 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001077 self.assertEqual(response.status, 401)
1078
jcgregorioadbb4f82006-05-19 15:17:42 +00001079 # Now add in credentials one at a time and test.
jcgregorio36140b52006-06-13 02:17:52 +00001080 self.http.add_credentials('joe', 'password')
jcgregorio2d66d4f2006-02-07 05:34:14 +00001081
1082 uri = urlparse.urljoin(base, "basic-nested/")
jcgregorio36140b52006-06-13 02:17:52 +00001083 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001084 self.assertEqual(response.status, 200)
1085
1086 uri = urlparse.urljoin(base, "basic-nested/subdir")
jcgregorio36140b52006-06-13 02:17:52 +00001087 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001088 self.assertEqual(response.status, 401)
1089
jcgregorio36140b52006-06-13 02:17:52 +00001090 self.http.add_credentials('fred', 'barney')
jcgregorio2d66d4f2006-02-07 05:34:14 +00001091
1092 uri = urlparse.urljoin(base, "basic-nested/")
jcgregorio36140b52006-06-13 02:17:52 +00001093 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001094 self.assertEqual(response.status, 200)
1095
1096 uri = urlparse.urljoin(base, "basic-nested/subdir")
jcgregorio36140b52006-06-13 02:17:52 +00001097 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001098 self.assertEqual(response.status, 200)
1099
1100 def testDigestAuth(self):
1101 # Test that we support Digest Authentication
1102 uri = urlparse.urljoin(base, "digest/")
jcgregorio36140b52006-06-13 02:17:52 +00001103 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001104 self.assertEqual(response.status, 401)
1105
jcgregorio36140b52006-06-13 02:17:52 +00001106 self.http.add_credentials('joe', 'password')
1107 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001108 self.assertEqual(response.status, 200)
1109
1110 uri = urlparse.urljoin(base, "digest/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001111 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001112
1113 def testDigestAuthNextNonceAndNC(self):
1114 # Test that if the server sets nextnonce that we reset
1115 # the nonce count back to 1
1116 uri = urlparse.urljoin(base, "digest/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001117 self.http.add_credentials('joe', 'password')
1118 (response, content) = self.http.request(uri, "GET", headers = {"cache-control":"no-cache"})
jcgregorio2d66d4f2006-02-07 05:34:14 +00001119 info = httplib2._parse_www_authenticate(response, 'authentication-info')
1120 self.assertEqual(response.status, 200)
jcgregorio36140b52006-06-13 02:17:52 +00001121 (response, content) = self.http.request(uri, "GET", headers = {"cache-control":"no-cache"})
jcgregorio2d66d4f2006-02-07 05:34:14 +00001122 info2 = httplib2._parse_www_authenticate(response, 'authentication-info')
1123 self.assertEqual(response.status, 200)
1124
1125 if info.has_key('nextnonce'):
1126 self.assertEqual(info2['nc'], 1)
1127
1128 def testDigestAuthStale(self):
1129 # Test that we can handle a nonce becoming stale
1130 uri = urlparse.urljoin(base, "digest-expire/file.txt")
jcgregorio36140b52006-06-13 02:17:52 +00001131 self.http.add_credentials('joe', 'password')
1132 (response, content) = self.http.request(uri, "GET", headers = {"cache-control":"no-cache"})
jcgregorio2d66d4f2006-02-07 05:34:14 +00001133 info = httplib2._parse_www_authenticate(response, 'authentication-info')
1134 self.assertEqual(response.status, 200)
1135
1136 time.sleep(3)
1137 # Sleep long enough that the nonce becomes stale
1138
jcgregorio36140b52006-06-13 02:17:52 +00001139 (response, content) = self.http.request(uri, "GET", headers = {"cache-control":"no-cache"})
jcgregorio2d66d4f2006-02-07 05:34:14 +00001140 self.assertFalse(response.fromcache)
1141 self.assertTrue(response._stale_digest)
1142 info3 = httplib2._parse_www_authenticate(response, 'authentication-info')
1143 self.assertEqual(response.status, 200)
1144
1145 def reflector(self, content):
jcgregorio25185622006-10-28 05:12:34 +00001146 return dict( [tuple(x.split("=", 1)) for x in content.strip().split("\n")] )
jcgregorio2d66d4f2006-02-07 05:34:14 +00001147
1148 def testReflector(self):
1149 uri = urlparse.urljoin(base, "reflector/reflector.cgi")
jcgregorio36140b52006-06-13 02:17:52 +00001150 (response, content) = self.http.request(uri, "GET")
jcgregorio2d66d4f2006-02-07 05:34:14 +00001151 d = self.reflector(content)
1152 self.assertTrue(d.has_key('HTTP_USER_AGENT'))
1153
Joe Gregorio84cc10a2009-09-01 13:02:49 -04001154 def testConnectionClose(self):
1155 uri = "http://www.google.com/"
1156 (response, content) = self.http.request(uri, "GET")
1157 for c in self.http.connections.values():
1158 self.assertNotEqual(None, c.sock)
1159 (response, content) = self.http.request(uri, "GET", headers={"connection": "close"})
1160 for c in self.http.connections.values():
1161 self.assertEqual(None, c.sock)
1162
1163
jcgregorio36140b52006-06-13 02:17:52 +00001164try:
1165 import memcache
1166 class HttpTestMemCached(HttpTest):
1167 def setUp(self):
1168 self.cache = memcache.Client(['127.0.0.1:11211'], debug=0)
jcgregorio47d24672006-06-29 05:18:59 +00001169 #self.cache = memcache.Client(['10.0.0.4:11211'], debug=1)
jcgregorio36140b52006-06-13 02:17:52 +00001170 self.http = httplib2.Http(self.cache)
1171 self.cache.flush_all()
jcgregorio47d24672006-06-29 05:18:59 +00001172 # Not exactly sure why the sleep is needed here, but
1173 # if not present then some unit tests that rely on caching
1174 # fail. Memcached seems to lose some sets immediately
1175 # after a flush_all if the set is to a value that
1176 # was previously cached. (Maybe the flush is handled async?)
1177 time.sleep(1)
jcgregorio36140b52006-06-13 02:17:52 +00001178 self.http.clear_credentials()
1179except:
1180 pass
1181
1182
1183
chris dent89f15142009-12-24 14:02:57 -06001184
jcgregoriodb8dfc82006-03-31 14:59:46 +00001185# ------------------------------------------------------------------------
jcgregorio2d66d4f2006-02-07 05:34:14 +00001186
1187class HttpPrivateTest(unittest.TestCase):
1188
1189 def testParseCacheControl(self):
1190 # Test that we can parse the Cache-Control header
1191 self.assertEqual({}, httplib2._parse_cache_control({}))
1192 self.assertEqual({'no-cache': 1}, httplib2._parse_cache_control({'cache-control': ' no-cache'}))
1193 cc = httplib2._parse_cache_control({'cache-control': ' no-cache, max-age = 7200'})
1194 self.assertEqual(cc['no-cache'], 1)
1195 self.assertEqual(cc['max-age'], '7200')
1196 cc = httplib2._parse_cache_control({'cache-control': ' , '})
1197 self.assertEqual(cc[''], 1)
1198
Joe Gregorioe314e8b2009-07-16 20:11:28 -04001199 try:
1200 cc = httplib2._parse_cache_control({'cache-control': 'Max-age=3600;post-check=1800,pre-check=3600'})
1201 self.assertTrue("max-age" in cc)
1202 except:
1203 self.fail("Should not throw exception")
1204
jcgregorio2d66d4f2006-02-07 05:34:14 +00001205 def testNormalizeHeaders(self):
1206 # Test that we normalize headers to lowercase
1207 h = httplib2._normalize_headers({'Cache-Control': 'no-cache', 'Other': 'Stuff'})
1208 self.assertTrue(h.has_key('cache-control'))
1209 self.assertTrue(h.has_key('other'))
1210 self.assertEqual('Stuff', h['other'])
1211
1212 def testExpirationModelTransparent(self):
1213 # Test that no-cache makes our request TRANSPARENT
1214 response_headers = {
1215 'cache-control': 'max-age=7200'
1216 }
1217 request_headers = {
1218 'cache-control': 'no-cache'
1219 }
1220 self.assertEqual("TRANSPARENT", httplib2._entry_disposition(response_headers, request_headers))
1221
jcgregorio45865012007-01-18 16:38:22 +00001222 def testMaxAgeNonNumeric(self):
1223 # Test that no-cache makes our request TRANSPARENT
1224 response_headers = {
1225 'cache-control': 'max-age=fred, min-fresh=barney'
1226 }
1227 request_headers = {
1228 }
1229 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1230
1231
jcgregorio2d66d4f2006-02-07 05:34:14 +00001232 def testExpirationModelNoCacheResponse(self):
1233 # The date and expires point to an entry that should be
1234 # FRESH, but the no-cache over-rides that.
1235 now = time.time()
1236 response_headers = {
1237 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)),
1238 'expires': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now+4)),
1239 'cache-control': 'no-cache'
1240 }
1241 request_headers = {
1242 }
1243 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1244
1245 def testExpirationModelStaleRequestMustReval(self):
1246 # must-revalidate forces STALE
1247 self.assertEqual("STALE", httplib2._entry_disposition({}, {'cache-control': 'must-revalidate'}))
1248
1249 def testExpirationModelStaleResponseMustReval(self):
1250 # must-revalidate forces STALE
1251 self.assertEqual("STALE", httplib2._entry_disposition({'cache-control': 'must-revalidate'}, {}))
1252
1253 def testExpirationModelFresh(self):
1254 response_headers = {
1255 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()),
1256 'cache-control': 'max-age=2'
1257 }
1258 request_headers = {
1259 }
1260 self.assertEqual("FRESH", httplib2._entry_disposition(response_headers, request_headers))
1261 time.sleep(3)
1262 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1263
1264 def testExpirationMaxAge0(self):
1265 response_headers = {
1266 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()),
1267 'cache-control': 'max-age=0'
1268 }
1269 request_headers = {
1270 }
1271 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1272
1273 def testExpirationModelDateAndExpires(self):
1274 now = time.time()
1275 response_headers = {
1276 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)),
1277 'expires': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now+2)),
1278 }
1279 request_headers = {
1280 }
1281 self.assertEqual("FRESH", httplib2._entry_disposition(response_headers, request_headers))
1282 time.sleep(3)
1283 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1284
jcgregoriof9511052007-06-01 14:56:34 +00001285 def testExpiresZero(self):
1286 now = time.time()
1287 response_headers = {
1288 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)),
1289 'expires': "0",
1290 }
1291 request_headers = {
1292 }
1293 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1294
jcgregorio2d66d4f2006-02-07 05:34:14 +00001295 def testExpirationModelDateOnly(self):
1296 now = time.time()
1297 response_headers = {
1298 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now+3)),
1299 }
1300 request_headers = {
1301 }
1302 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1303
1304 def testExpirationModelOnlyIfCached(self):
1305 response_headers = {
1306 }
1307 request_headers = {
1308 'cache-control': 'only-if-cached',
1309 }
1310 self.assertEqual("FRESH", httplib2._entry_disposition(response_headers, request_headers))
1311
1312 def testExpirationModelMaxAgeBoth(self):
1313 now = time.time()
1314 response_headers = {
1315 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)),
1316 'cache-control': 'max-age=2'
1317 }
1318 request_headers = {
1319 'cache-control': 'max-age=0'
1320 }
1321 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1322
1323 def testExpirationModelDateAndExpiresMinFresh1(self):
1324 now = time.time()
1325 response_headers = {
1326 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)),
1327 'expires': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now+2)),
1328 }
1329 request_headers = {
1330 'cache-control': 'min-fresh=2'
1331 }
1332 self.assertEqual("STALE", httplib2._entry_disposition(response_headers, request_headers))
1333
1334 def testExpirationModelDateAndExpiresMinFresh2(self):
1335 now = time.time()
1336 response_headers = {
1337 'date': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)),
1338 'expires': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now+4)),
1339 }
1340 request_headers = {
1341 'cache-control': 'min-fresh=2'
1342 }
1343 self.assertEqual("FRESH", httplib2._entry_disposition(response_headers, request_headers))
1344
1345 def testParseWWWAuthenticateEmpty(self):
1346 res = httplib2._parse_www_authenticate({})
1347 self.assertEqual(len(res.keys()), 0)
1348
jcgregoriofd22e432006-04-27 02:00:08 +00001349 def testParseWWWAuthenticate(self):
1350 # different uses of spaces around commas
1351 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Test realm="test realm" , foo=foo ,bar="bar", baz=baz,qux=qux'})
1352 self.assertEqual(len(res.keys()), 1)
1353 self.assertEqual(len(res['test'].keys()), 5)
1354
1355 # tokens with non-alphanum
1356 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'T*!%#st realm=to*!%#en, to*!%#en="quoted string"'})
1357 self.assertEqual(len(res.keys()), 1)
1358 self.assertEqual(len(res['t*!%#st'].keys()), 2)
1359
1360 # quoted string with quoted pairs
1361 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Test realm="a \\"test\\" realm"'})
1362 self.assertEqual(len(res.keys()), 1)
1363 self.assertEqual(res['test']['realm'], 'a "test" realm')
1364
1365 def testParseWWWAuthenticateStrict(self):
1366 httplib2.USE_WWW_AUTH_STRICT_PARSING = 1;
1367 self.testParseWWWAuthenticate();
1368 httplib2.USE_WWW_AUTH_STRICT_PARSING = 0;
1369
jcgregorio2d66d4f2006-02-07 05:34:14 +00001370 def testParseWWWAuthenticateBasic(self):
1371 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Basic realm="me"'})
1372 basic = res['basic']
1373 self.assertEqual('me', basic['realm'])
1374
1375 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Basic realm="me", algorithm="MD5"'})
1376 basic = res['basic']
1377 self.assertEqual('me', basic['realm'])
1378 self.assertEqual('MD5', basic['algorithm'])
1379
1380 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Basic realm="me", algorithm=MD5'})
1381 basic = res['basic']
1382 self.assertEqual('me', basic['realm'])
1383 self.assertEqual('MD5', basic['algorithm'])
1384
1385 def testParseWWWAuthenticateBasic2(self):
1386 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Basic realm="me",other="fred" '})
1387 basic = res['basic']
1388 self.assertEqual('me', basic['realm'])
1389 self.assertEqual('fred', basic['other'])
1390
1391 def testParseWWWAuthenticateBasic3(self):
1392 res = httplib2._parse_www_authenticate({ 'www-authenticate': 'Basic REAlm="me" '})
1393 basic = res['basic']
1394 self.assertEqual('me', basic['realm'])
1395
1396
1397 def testParseWWWAuthenticateDigest(self):
1398 res = httplib2._parse_www_authenticate({ 'www-authenticate':
1399 'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"'})
1400 digest = res['digest']
1401 self.assertEqual('testrealm@host.com', digest['realm'])
1402 self.assertEqual('auth,auth-int', digest['qop'])
1403
1404
1405 def testParseWWWAuthenticateMultiple(self):
1406 res = httplib2._parse_www_authenticate({ 'www-authenticate':
1407 'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41" Basic REAlm="me" '})
1408 digest = res['digest']
1409 self.assertEqual('testrealm@host.com', digest['realm'])
1410 self.assertEqual('auth,auth-int', digest['qop'])
1411 self.assertEqual('dcd98b7102dd2f0e8b11d0f600bfb0c093', digest['nonce'])
1412 self.assertEqual('5ccc069c403ebaf9f0171e9517f40e41', digest['opaque'])
1413 basic = res['basic']
1414 self.assertEqual('me', basic['realm'])
1415
1416 def testParseWWWAuthenticateMultiple2(self):
1417 # Handle an added comma between challenges, which might get thrown in if the challenges were
1418 # originally sent in separate www-authenticate headers.
1419 res = httplib2._parse_www_authenticate({ 'www-authenticate':
1420 'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41", Basic REAlm="me" '})
1421 digest = res['digest']
1422 self.assertEqual('testrealm@host.com', digest['realm'])
1423 self.assertEqual('auth,auth-int', digest['qop'])
1424 self.assertEqual('dcd98b7102dd2f0e8b11d0f600bfb0c093', digest['nonce'])
1425 self.assertEqual('5ccc069c403ebaf9f0171e9517f40e41', digest['opaque'])
1426 basic = res['basic']
1427 self.assertEqual('me', basic['realm'])
1428
1429 def testParseWWWAuthenticateMultiple3(self):
1430 # Handle an added comma between challenges, which might get thrown in if the challenges were
1431 # originally sent in separate www-authenticate headers.
1432 res = httplib2._parse_www_authenticate({ 'www-authenticate':
1433 'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41", Basic REAlm="me", WSSE realm="foo", profile="UsernameToken"'})
1434 digest = res['digest']
1435 self.assertEqual('testrealm@host.com', digest['realm'])
1436 self.assertEqual('auth,auth-int', digest['qop'])
1437 self.assertEqual('dcd98b7102dd2f0e8b11d0f600bfb0c093', digest['nonce'])
1438 self.assertEqual('5ccc069c403ebaf9f0171e9517f40e41', digest['opaque'])
1439 basic = res['basic']
1440 self.assertEqual('me', basic['realm'])
1441 wsse = res['wsse']
1442 self.assertEqual('foo', wsse['realm'])
1443 self.assertEqual('UsernameToken', wsse['profile'])
1444
1445 def testParseWWWAuthenticateMultiple4(self):
1446 res = httplib2._parse_www_authenticate({ 'www-authenticate':
1447 'Digest realm="test-real.m@host.com", qop \t=\t"\tauth,auth-int", nonce="(*)&^&$%#",opaque="5ccc069c403ebaf9f0171e9517f40e41", Basic REAlm="me", WSSE realm="foo", profile="UsernameToken"'})
1448 digest = res['digest']
1449 self.assertEqual('test-real.m@host.com', digest['realm'])
1450 self.assertEqual('\tauth,auth-int', digest['qop'])
1451 self.assertEqual('(*)&^&$%#', digest['nonce'])
1452
1453 def testParseWWWAuthenticateMoreQuoteCombos(self):
1454 res = httplib2._parse_www_authenticate({'www-authenticate':'Digest realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", algorithm=MD5, qop="auth", stale=true'})
1455 digest = res['digest']
1456 self.assertEqual('myrealm', digest['realm'])
1457
Joe Gregorio6fa3cf22011-02-13 22:45:06 -05001458 def testParseWWWAuthenticateMalformed(self):
1459 try:
1460 res = httplib2._parse_www_authenticate({'www-authenticate':'OAuth "Facebook Platform" "invalid_token" "Invalid OAuth access token."'})
1461 self.fail("should raise an exception")
1462 except httplib2.MalformedHeader:
1463 pass
1464
jcgregorio2d66d4f2006-02-07 05:34:14 +00001465 def testDigestObject(self):
1466 credentials = ('joe', 'password')
1467 host = None
1468 request_uri = '/projects/httplib2/test/digest/'
1469 headers = {}
1470 response = {
1471 'www-authenticate': 'Digest realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", algorithm=MD5, qop="auth"'
1472 }
1473 content = ""
Joe Gregorio875a8b52011-06-13 14:06:23 -04001474
jcgregorio6cbab7e2006-04-21 20:35:43 +00001475 d = httplib2.DigestAuthentication(credentials, host, request_uri, headers, response, content, None)
jcgregorio2d66d4f2006-02-07 05:34:14 +00001476 d.request("GET", request_uri, headers, content, cnonce="33033375ec278a46")
Joe Gregorio875a8b52011-06-13 14:06:23 -04001477 our_request = "authorization: %s" % headers['authorization']
1478 working_request = 'authorization: Digest username="joe", realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", uri="/projects/httplib2/test/digest/", algorithm=MD5, response="97ed129401f7cdc60e5db58a80f3ea8b", qop=auth, nc=00000001, cnonce="33033375ec278a46"'
jcgregorio2d66d4f2006-02-07 05:34:14 +00001479 self.assertEqual(our_request, working_request)
1480
Joe Gregorio03d99102011-06-22 16:55:52 -04001481 def testDigestObjectWithOpaque(self):
1482 credentials = ('joe', 'password')
1483 host = None
1484 request_uri = '/projects/httplib2/test/digest/'
1485 headers = {}
1486 response = {
1487 'www-authenticate': 'Digest realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", algorithm=MD5, qop="auth", opaque="atestopaque"'
1488 }
1489 content = ""
1490
1491 d = httplib2.DigestAuthentication(credentials, host, request_uri, headers, response, content, None)
1492 d.request("GET", request_uri, headers, content, cnonce="33033375ec278a46")
1493 our_request = "authorization: %s" % headers['authorization']
1494 working_request = 'authorization: Digest username="joe", realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", uri="/projects/httplib2/test/digest/", algorithm=MD5, response="97ed129401f7cdc60e5db58a80f3ea8b", qop=auth, nc=00000001, cnonce="33033375ec278a46", opaque="atestopaque"'
1495 self.assertEqual(our_request, working_request)
jcgregorio2d66d4f2006-02-07 05:34:14 +00001496
1497 def testDigestObjectStale(self):
1498 credentials = ('joe', 'password')
1499 host = None
1500 request_uri = '/projects/httplib2/test/digest/'
1501 headers = {}
1502 response = httplib2.Response({ })
1503 response['www-authenticate'] = 'Digest realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", algorithm=MD5, qop="auth", stale=true'
1504 response.status = 401
1505 content = ""
jcgregorio6cbab7e2006-04-21 20:35:43 +00001506 d = httplib2.DigestAuthentication(credentials, host, request_uri, headers, response, content, None)
jcgregorio2d66d4f2006-02-07 05:34:14 +00001507 # Returns true to force a retry
1508 self.assertTrue( d.response(response, content) )
1509
1510 def testDigestObjectAuthInfo(self):
1511 credentials = ('joe', 'password')
1512 host = None
1513 request_uri = '/projects/httplib2/test/digest/'
1514 headers = {}
1515 response = httplib2.Response({ })
1516 response['www-authenticate'] = 'Digest realm="myrealm", nonce="Ygk86AsKBAA=3516200d37f9a3230352fde99977bd6d472d4306", algorithm=MD5, qop="auth", stale=true'
1517 response['authentication-info'] = 'nextnonce="fred"'
1518 content = ""
jcgregorio6cbab7e2006-04-21 20:35:43 +00001519 d = httplib2.DigestAuthentication(credentials, host, request_uri, headers, response, content, None)
jcgregorio2d66d4f2006-02-07 05:34:14 +00001520 # Returns true to force a retry
1521 self.assertFalse( d.response(response, content) )
1522 self.assertEqual('fred', d.challenge['nonce'])
1523 self.assertEqual(1, d.challenge['nc'])
1524
1525 def testWsseAlgorithm(self):
1526 digest = httplib2._wsse_username_token("d36e316282959a9ed4c89851497a717f", "2003-12-15T14:43:07Z", "taadtaadpstcsm")
1527 expected = "quR/EWLAV4xLf9Zqyw4pDmfV9OY="
1528 self.assertEqual(expected, digest)
1529
jcgregoriodb8dfc82006-03-31 14:59:46 +00001530 def testEnd2End(self):
1531 # one end to end header
1532 response = {'content-type': 'application/atom+xml', 'te': 'deflate'}
1533 end2end = httplib2._get_end2end_headers(response)
1534 self.assertTrue('content-type' in end2end)
1535 self.assertTrue('te' not in end2end)
1536 self.assertTrue('connection' not in end2end)
1537
1538 # one end to end header that gets eliminated
1539 response = {'connection': 'content-type', 'content-type': 'application/atom+xml', 'te': 'deflate'}
1540 end2end = httplib2._get_end2end_headers(response)
1541 self.assertTrue('content-type' not in end2end)
1542 self.assertTrue('te' not in end2end)
1543 self.assertTrue('connection' not in end2end)
1544
1545 # Degenerate case of no headers
1546 response = {}
1547 end2end = httplib2._get_end2end_headers(response)
1548 self.assertEquals(0, len(end2end))
1549
1550 # Degenerate case of connection referrring to a header not passed in
1551 response = {'connection': 'content-type'}
1552 end2end = httplib2._get_end2end_headers(response)
1553 self.assertEquals(0, len(end2end))
jcgregorio2d66d4f2006-02-07 05:34:14 +00001554
Jason R. Coombs8a487d02011-08-09 09:35:58 -04001555
1556class TestProxyInfo(unittest.TestCase):
1557 def setUp(self):
1558 self.orig_env = dict(os.environ)
1559
1560 def tearDown(self):
1561 os.environ.clear()
1562 os.environ.update(self.orig_env)
1563
1564 def test_from_url(self):
1565 pi = httplib2.ProxyInfo.from_url('http://myproxy.example.com')
1566 self.assertEquals(pi.proxy_host, 'myproxy.example.com')
1567 self.assertEquals(pi.proxy_port, 80)
1568 self.assertEquals(pi.proxy_user, None)
1569
1570 def test_from_url_ident(self):
1571 pi = httplib2.ProxyInfo.from_url('http://zoidberg:fish@someproxy:99')
1572 self.assertEquals(pi.proxy_host, 'someproxy')
1573 self.assertEquals(pi.proxy_port, 99)
1574 self.assertEquals(pi.proxy_user, 'zoidberg')
1575 self.assertEquals(pi.proxy_pass, 'fish')
1576
1577 def test_from_env(self):
1578 os.environ['http_proxy'] = 'http://myproxy.example.com:8080'
1579 pi = httplib2.ProxyInfo.from_environment()
1580 self.assertEquals(pi.proxy_host, 'myproxy.example.com')
1581 self.assertEquals(pi.proxy_port, 8080)
1582 self.assertEquals(pi.bypass_hosts, [])
1583
1584 def test_from_env_no_proxy(self):
1585 os.environ['http_proxy'] = 'http://myproxy.example.com:80'
1586 os.environ['https_proxy'] = 'http://myproxy.example.com:81'
1587 os.environ['no_proxy'] = 'localhost,otherhost.domain.local'
1588 pi = httplib2.ProxyInfo.from_environment('https')
1589 self.assertEquals(pi.proxy_host, 'myproxy.example.com')
1590 self.assertEquals(pi.proxy_port, 81)
1591 self.assertEquals(pi.bypass_hosts, ['localhost',
1592 'otherhost.domain.local'])
1593
1594 def test_from_env_none(self):
1595 os.environ.clear()
1596 pi = httplib2.ProxyInfo.from_environment()
1597 self.assertEquals(pi, None)
1598
Jason R. Coombs43840892011-08-09 10:30:46 -04001599 def test_applies_to(self):
1600 os.environ['http_proxy'] = 'http://myproxy.example.com:80'
1601 os.environ['https_proxy'] = 'http://myproxy.example.com:81'
Jason R. Coombs96279c52011-08-16 12:53:27 -04001602 os.environ['no_proxy'] = 'localhost,otherhost.domain.local,example.com'
Jason R. Coombs43840892011-08-09 10:30:46 -04001603 pi = httplib2.ProxyInfo.from_environment()
1604 self.assertFalse(pi.applies_to('localhost'))
1605 self.assertTrue(pi.applies_to('www.google.com'))
Jason R. Coombs96279c52011-08-16 12:53:27 -04001606 self.assertFalse(pi.applies_to('www.example.com'))
1607
1608 def test_no_proxy_star(self):
1609 os.environ['http_proxy'] = 'http://myproxy.example.com:80'
1610 os.environ['NO_PROXY'] = '*'
1611 pi = httplib2.ProxyInfo.from_environment()
1612 for host in ('localhost', '169.254.38.192', 'www.google.com'):
1613 self.assertFalse(pi.applies_to(host))
Jason R. Coombs43840892011-08-09 10:30:46 -04001614
Jason R. Coombs8a487d02011-08-09 09:35:58 -04001615
chris dent89f15142009-12-24 14:02:57 -06001616if __name__ == '__main__':
1617 unittest.main()