blob: 9320e61c4ea211de20478c91266e2289523b7e85 [file] [log] [blame]
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002from test import support
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00003
Christian Heimes05e8be12008-02-23 18:30:17 +00004import os
Guido van Rossum34d19282007-08-09 01:03:29 +00005import io
Georg Brandlf78e02b2008-06-10 17:40:04 +00006import socket
Jeremy Hyltone3e61042001-05-09 15:50:25 +00007
Jeremy Hylton1afc1692008-06-18 20:49:58 +00008import urllib.request
9from urllib.request import Request, OpenerDirector
Jeremy Hyltone3e61042001-05-09 15:50:25 +000010
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000011# XXX
12# Request
13# CacheFTPHandler (hard to write)
Thomas Wouters477c8d52006-05-27 19:21:47 +000014# parse_keqv_list, parse_http_list, HTTPDigestAuthHandler
Jeremy Hyltone3e61042001-05-09 15:50:25 +000015
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000016class TrivialTests(unittest.TestCase):
17 def test_trivial(self):
18 # A couple trivial tests
Guido van Rossume2ae77b2001-10-24 20:42:55 +000019
Jeremy Hylton1afc1692008-06-18 20:49:58 +000020 self.assertRaises(ValueError, urllib.request.urlopen, 'bogus url')
Tim Peters861adac2001-07-16 20:49:49 +000021
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000022 # XXX Name hacking to get this to work on Windows.
Jeremy Hylton1afc1692008-06-18 20:49:58 +000023 fname = os.path.abspath(urllib.request.__file__).replace('\\', '/')
Senthil Kumaran673d7e92010-01-10 17:48:37 +000024
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000025 # And more hacking to get it to work on MacOS. This assumes
26 # urllib.pathname2url works, unfortunately...
27 if os.name == 'mac':
28 fname = '/' + fname.replace(':', '/')
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000029
Senthil Kumaran673d7e92010-01-10 17:48:37 +000030 if os.name == 'nt':
31 file_url = "file:///%s" % fname
32 else:
33 file_url = "file://%s" % fname
34
Jeremy Hylton1afc1692008-06-18 20:49:58 +000035 f = urllib.request.urlopen(file_url)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000036
37 buf = f.read()
38 f.close()
Tim Petersf5f32b42005-07-17 23:16:17 +000039
Georg Brandle1b13d22005-08-24 22:20:32 +000040 def test_parse_http_list(self):
Jeremy Hylton1afc1692008-06-18 20:49:58 +000041 tests = [
42 ('a,b,c', ['a', 'b', 'c']),
43 ('path"o,l"og"i"cal, example', ['path"o,l"og"i"cal', 'example']),
44 ('a, b, "c", "d", "e,f", g, h',
45 ['a', 'b', '"c"', '"d"', '"e,f"', 'g', 'h']),
46 ('a="b\\"c", d="e\\,f", g="h\\\\i"',
47 ['a="b"c"', 'd="e,f"', 'g="h\\i"'])]
Georg Brandle1b13d22005-08-24 22:20:32 +000048 for string, list in tests:
Florent Xiclunab4efb3d2010-08-14 18:24:40 +000049 self.assertEqual(urllib.request.parse_http_list(string), list)
Georg Brandle1b13d22005-08-24 22:20:32 +000050
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +000051
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000052def test_request_headers_dict():
53 """
54 The Request.headers dictionary is not a documented interface. It should
55 stay that way, because the complete set of headers are only accessible
56 through the .get_header(), .has_header(), .header_items() interface.
57 However, .headers pre-dates those methods, and so real code will be using
58 the dictionary.
59
60 The introduction in 2.4 of those methods was a mistake for the same reason:
61 code that previously saw all (urllib2 user)-provided headers in .headers
62 now sees only a subset (and the function interface is ugly and incomplete).
63 A better change would have been to replace .headers dict with a dict
64 subclass (or UserDict.DictMixin instance?) that preserved the .headers
65 interface and also provided access to the "unredirected" headers. It's
66 probably too late to fix that, though.
67
68
69 Check .capitalize() case normalization:
70
71 >>> url = "http://example.com"
72 >>> Request(url, headers={"Spam-eggs": "blah"}).headers["Spam-eggs"]
73 'blah'
74 >>> Request(url, headers={"spam-EggS": "blah"}).headers["Spam-eggs"]
75 'blah'
76
77 Currently, Request(url, "Spam-eggs").headers["Spam-Eggs"] raises KeyError,
78 but that could be changed in future.
79
80 """
81
82def test_request_headers_methods():
83 """
84 Note the case normalization of header names here, to .capitalize()-case.
85 This should be preserved for backwards-compatibility. (In the HTTP case,
86 normalization to .title()-case is done by urllib2 before sending headers to
Georg Brandl24420152008-05-26 16:32:26 +000087 http.client).
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088
89 >>> url = "http://example.com"
90 >>> r = Request(url, headers={"Spam-eggs": "blah"})
91 >>> r.has_header("Spam-eggs")
92 True
93 >>> r.header_items()
94 [('Spam-eggs', 'blah')]
95 >>> r.add_header("Foo-Bar", "baz")
Guido van Rossumcc2b0162007-02-11 06:12:03 +000096 >>> items = sorted(r.header_items())
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000097 >>> items
98 [('Foo-bar', 'baz'), ('Spam-eggs', 'blah')]
99
100 Note that e.g. r.has_header("spam-EggS") is currently False, and
101 r.get_header("spam-EggS") returns None, but that could be changed in
102 future.
103
104 >>> r.has_header("Not-there")
105 False
Guido van Rossum7131f842007-02-09 20:13:25 +0000106 >>> print(r.get_header("Not-there"))
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000107 None
108 >>> r.get_header("Not-there", "default")
109 'default'
110
111 """
112
113
Thomas Wouters477c8d52006-05-27 19:21:47 +0000114def test_password_manager(self):
115 """
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000116 >>> mgr = urllib.request.HTTPPasswordMgr()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000117 >>> add = mgr.add_password
118 >>> add("Some Realm", "http://example.com/", "joe", "password")
119 >>> add("Some Realm", "http://example.com/ni", "ni", "ni")
120 >>> add("c", "http://example.com/foo", "foo", "ni")
121 >>> add("c", "http://example.com/bar", "bar", "nini")
122 >>> add("b", "http://example.com/", "first", "blah")
123 >>> add("b", "http://example.com/", "second", "spam")
124 >>> add("a", "http://example.com", "1", "a")
125 >>> add("Some Realm", "http://c.example.com:3128", "3", "c")
126 >>> add("Some Realm", "d.example.com", "4", "d")
127 >>> add("Some Realm", "e.example.com:3128", "5", "e")
128
129 >>> mgr.find_user_password("Some Realm", "example.com")
130 ('joe', 'password')
131 >>> mgr.find_user_password("Some Realm", "http://example.com")
132 ('joe', 'password')
133 >>> mgr.find_user_password("Some Realm", "http://example.com/")
134 ('joe', 'password')
135 >>> mgr.find_user_password("Some Realm", "http://example.com/spam")
136 ('joe', 'password')
137 >>> mgr.find_user_password("Some Realm", "http://example.com/spam/spam")
138 ('joe', 'password')
139 >>> mgr.find_user_password("c", "http://example.com/foo")
140 ('foo', 'ni')
141 >>> mgr.find_user_password("c", "http://example.com/bar")
142 ('bar', 'nini')
143
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000144 Actually, this is really undefined ATM
145## Currently, we use the highest-level path where more than one match:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000146
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000147## >>> mgr.find_user_password("Some Realm", "http://example.com/ni")
148## ('joe', 'password')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000149
150 Use latest add_password() in case of conflict:
151
152 >>> mgr.find_user_password("b", "http://example.com/")
153 ('second', 'spam')
154
155 No special relationship between a.example.com and example.com:
156
157 >>> mgr.find_user_password("a", "http://example.com/")
158 ('1', 'a')
159 >>> mgr.find_user_password("a", "http://a.example.com/")
160 (None, None)
161
162 Ports:
163
164 >>> mgr.find_user_password("Some Realm", "c.example.com")
165 (None, None)
166 >>> mgr.find_user_password("Some Realm", "c.example.com:3128")
167 ('3', 'c')
168 >>> mgr.find_user_password("Some Realm", "http://c.example.com:3128")
169 ('3', 'c')
170 >>> mgr.find_user_password("Some Realm", "d.example.com")
171 ('4', 'd')
172 >>> mgr.find_user_password("Some Realm", "e.example.com:3128")
173 ('5', 'e')
174
175 """
176 pass
177
178
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000179def test_password_manager_default_port(self):
180 """
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000181 >>> mgr = urllib.request.HTTPPasswordMgr()
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000182 >>> add = mgr.add_password
183
184 The point to note here is that we can't guess the default port if there's
185 no scheme. This applies to both add_password and find_user_password.
186
187 >>> add("f", "http://g.example.com:80", "10", "j")
188 >>> add("g", "http://h.example.com", "11", "k")
189 >>> add("h", "i.example.com:80", "12", "l")
190 >>> add("i", "j.example.com", "13", "m")
191 >>> mgr.find_user_password("f", "g.example.com:100")
192 (None, None)
193 >>> mgr.find_user_password("f", "g.example.com:80")
194 ('10', 'j')
195 >>> mgr.find_user_password("f", "g.example.com")
196 (None, None)
197 >>> mgr.find_user_password("f", "http://g.example.com:100")
198 (None, None)
199 >>> mgr.find_user_password("f", "http://g.example.com:80")
200 ('10', 'j')
201 >>> mgr.find_user_password("f", "http://g.example.com")
202 ('10', 'j')
203 >>> mgr.find_user_password("g", "h.example.com")
204 ('11', 'k')
205 >>> mgr.find_user_password("g", "h.example.com:80")
206 ('11', 'k')
207 >>> mgr.find_user_password("g", "http://h.example.com:80")
208 ('11', 'k')
209 >>> mgr.find_user_password("h", "i.example.com")
210 (None, None)
211 >>> mgr.find_user_password("h", "i.example.com:80")
212 ('12', 'l')
213 >>> mgr.find_user_password("h", "http://i.example.com:80")
214 ('12', 'l')
215 >>> mgr.find_user_password("i", "j.example.com")
216 ('13', 'm')
217 >>> mgr.find_user_password("i", "j.example.com:80")
218 (None, None)
219 >>> mgr.find_user_password("i", "http://j.example.com")
220 ('13', 'm')
221 >>> mgr.find_user_password("i", "http://j.example.com:80")
222 (None, None)
223
224 """
225
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000226class MockOpener:
227 addheaders = []
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000228 def open(self, req, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
229 self.req, self.data, self.timeout = req, data, timeout
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000230 def error(self, proto, *args):
231 self.proto, self.args = proto, args
232
233class MockFile:
234 def read(self, count=None): pass
235 def readline(self, count=None): pass
236 def close(self): pass
237
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000238class MockHeaders(dict):
239 def getheaders(self, name):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000240 return list(self.values())
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000241
Guido van Rossum34d19282007-08-09 01:03:29 +0000242class MockResponse(io.StringIO):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000243 def __init__(self, code, msg, headers, data, url=None):
Guido van Rossum34d19282007-08-09 01:03:29 +0000244 io.StringIO.__init__(self, data)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000245 self.code, self.msg, self.headers, self.url = code, msg, headers, url
246 def info(self):
247 return self.headers
248 def geturl(self):
249 return self.url
250
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000251class MockCookieJar:
252 def add_cookie_header(self, request):
253 self.ach_req = request
254 def extract_cookies(self, response, request):
255 self.ec_req, self.ec_r = request, response
256
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000257class FakeMethod:
258 def __init__(self, meth_name, action, handle):
259 self.meth_name = meth_name
260 self.handle = handle
261 self.action = action
262 def __call__(self, *args):
263 return self.handle(self.meth_name, self.action, *args)
264
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +0000265class MockHTTPResponse(io.IOBase):
266 def __init__(self, fp, msg, status, reason):
267 self.fp = fp
268 self.msg = msg
269 self.status = status
270 self.reason = reason
271 self.code = 200
272
273 def read(self):
274 return ''
275
276 def info(self):
277 return {}
278
279 def geturl(self):
280 return self.url
281
282
283class MockHTTPClass:
284 def __init__(self):
285 self.level = 0
286 self.req_headers = []
287 self.data = None
288 self.raise_on_endheaders = False
289 self._tunnel_headers = {}
290
291 def __call__(self, host, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
292 self.host = host
293 self.timeout = timeout
294 return self
295
296 def set_debuglevel(self, level):
297 self.level = level
298
299 def _set_tunnel(self, host, port=None, headers=None):
300 self._tunnel_host = host
301 self._tunnel_port = port
302 if headers:
303 self._tunnel_headers = headers
304 else:
305 self._tunnel_headers.clear()
306
Benjamin Peterson794921a2009-12-24 01:18:13 +0000307 def request(self, method, url, body=None, headers=None):
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +0000308 self.method = method
309 self.selector = url
Benjamin Peterson794921a2009-12-24 01:18:13 +0000310 if headers is not None:
311 self.req_headers += headers.items()
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +0000312 self.req_headers.sort()
313 if body:
314 self.data = body
315 if self.raise_on_endheaders:
316 import socket
317 raise socket.error()
318 def getresponse(self):
319 return MockHTTPResponse(MockFile(), {}, 200, "OK")
320
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000321class MockHandler:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000322 # useful for testing handler machinery
323 # see add_ordered_mock_handlers() docstring
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000324 handler_order = 500
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000325 def __init__(self, methods):
326 self._define_methods(methods)
327 def _define_methods(self, methods):
328 for spec in methods:
329 if len(spec) == 2: name, action = spec
330 else: name, action = spec, None
331 meth = FakeMethod(name, action, self.handle)
332 setattr(self.__class__, name, meth)
333 def handle(self, fn_name, action, *args, **kwds):
334 self.parent.calls.append((self, fn_name, args, kwds))
335 if action is None:
336 return None
337 elif action == "return self":
338 return self
339 elif action == "return response":
340 res = MockResponse(200, "OK", {}, "")
341 return res
342 elif action == "return request":
343 return Request("http://blah/")
344 elif action.startswith("error"):
345 code = action[action.rfind(" ")+1:]
346 try:
347 code = int(code)
348 except ValueError:
349 pass
350 res = MockResponse(200, "OK", {}, "")
351 return self.parent.error("http", args[0], res, code, "", {})
352 elif action == "raise":
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000353 raise urllib.error.URLError("blah")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000354 assert False
355 def close(self): pass
356 def add_parent(self, parent):
357 self.parent = parent
358 self.parent.calls = []
359 def __lt__(self, other):
360 if not hasattr(other, "handler_order"):
361 # No handler_order, leave in original order. Yuck.
362 return True
363 return self.handler_order < other.handler_order
364
365def add_ordered_mock_handlers(opener, meth_spec):
366 """Create MockHandlers and add them to an OpenerDirector.
367
368 meth_spec: list of lists of tuples and strings defining methods to define
369 on handlers. eg:
370
371 [["http_error", "ftp_open"], ["http_open"]]
372
373 defines methods .http_error() and .ftp_open() on one handler, and
374 .http_open() on another. These methods just record their arguments and
375 return None. Using a tuple instead of a string causes the method to
376 perform some action (see MockHandler.handle()), eg:
377
378 [["http_error"], [("http_open", "return request")]]
379
380 defines .http_error() on one handler (which simply returns None), and
381 .http_open() on another handler, which returns a Request object.
382
383 """
384 handlers = []
385 count = 0
386 for meths in meth_spec:
387 class MockHandlerSubclass(MockHandler): pass
388 h = MockHandlerSubclass(meths)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000389 h.handler_order += count
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000390 h.add_parent(opener)
391 count = count + 1
392 handlers.append(h)
393 opener.add_handler(h)
394 return handlers
395
Thomas Wouters477c8d52006-05-27 19:21:47 +0000396def build_test_opener(*handler_instances):
397 opener = OpenerDirector()
398 for h in handler_instances:
399 opener.add_handler(h)
400 return opener
401
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000402class MockHTTPHandler(urllib.request.BaseHandler):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000403 # useful for testing redirections and auth
404 # sends supplied headers and code as first response
405 # sends 200 OK as second response
406 def __init__(self, code, headers):
407 self.code = code
408 self.headers = headers
409 self.reset()
410 def reset(self):
411 self._count = 0
412 self.requests = []
413 def http_open(self, req):
Barry Warsaw820c1202008-06-12 04:06:45 +0000414 import email, http.client, copy
Guido van Rossum34d19282007-08-09 01:03:29 +0000415 from io import StringIO
Thomas Wouters477c8d52006-05-27 19:21:47 +0000416 self.requests.append(copy.deepcopy(req))
417 if self._count == 0:
418 self._count = self._count + 1
Georg Brandl24420152008-05-26 16:32:26 +0000419 name = http.client.responses[self.code]
Barry Warsaw820c1202008-06-12 04:06:45 +0000420 msg = email.message_from_string(self.headers)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000421 return self.parent.error(
422 "http", req, MockFile(), self.code, name, msg)
423 else:
424 self.req = req
Barry Warsaw820c1202008-06-12 04:06:45 +0000425 msg = email.message_from_string("\r\n\r\n")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000426 return MockResponse(200, "OK", msg, "", req.get_full_url())
427
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +0000428class MockHTTPSHandler(urllib.request.AbstractHTTPHandler):
429 # Useful for testing the Proxy-Authorization request by verifying the
430 # properties of httpcon
Benjamin Peterson794921a2009-12-24 01:18:13 +0000431
432 def __init__(self):
433 urllib.request.AbstractHTTPHandler.__init__(self)
434 self.httpconn = MockHTTPClass()
435
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +0000436 def https_open(self, req):
437 return self.do_open(self.httpconn, req)
438
Thomas Wouters477c8d52006-05-27 19:21:47 +0000439class MockPasswordManager:
440 def add_password(self, realm, uri, user, password):
441 self.realm = realm
442 self.url = uri
443 self.user = user
444 self.password = password
445 def find_user_password(self, realm, authuri):
446 self.target_realm = realm
447 self.target_url = authuri
448 return self.user, self.password
449
450
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000451class OpenerDirectorTests(unittest.TestCase):
452
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000453 def test_add_non_handler(self):
454 class NonHandler(object):
455 pass
456 self.assertRaises(TypeError,
457 OpenerDirector().add_handler, NonHandler())
458
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000459 def test_badly_named_methods(self):
460 # test work-around for three methods that accidentally follow the
461 # naming conventions for handler methods
462 # (*_open() / *_request() / *_response())
463
464 # These used to call the accidentally-named methods, causing a
465 # TypeError in real code; here, returning self from these mock
466 # methods would either cause no exception, or AttributeError.
467
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000468 from urllib.error import URLError
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000469
470 o = OpenerDirector()
471 meth_spec = [
472 [("do_open", "return self"), ("proxy_open", "return self")],
473 [("redirect_request", "return self")],
474 ]
475 handlers = add_ordered_mock_handlers(o, meth_spec)
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000476 o.add_handler(urllib.request.UnknownHandler())
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000477 for scheme in "do", "proxy", "redirect":
478 self.assertRaises(URLError, o.open, scheme+"://example.com/")
479
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000480 def test_handled(self):
481 # handler returning non-None means no more handlers will be called
482 o = OpenerDirector()
483 meth_spec = [
484 ["http_open", "ftp_open", "http_error_302"],
485 ["ftp_open"],
486 [("http_open", "return self")],
487 [("http_open", "return self")],
488 ]
489 handlers = add_ordered_mock_handlers(o, meth_spec)
490
491 req = Request("http://example.com/")
492 r = o.open(req)
493 # Second .http_open() gets called, third doesn't, since second returned
494 # non-None. Handlers without .http_open() never get any methods called
495 # on them.
496 # In fact, second mock handler defining .http_open() returns self
497 # (instead of response), which becomes the OpenerDirector's return
498 # value.
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000499 self.assertEqual(r, handlers[2])
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000500 calls = [(handlers[0], "http_open"), (handlers[2], "http_open")]
501 for expected, got in zip(calls, o.calls):
502 handler, name, args, kwds = got
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000503 self.assertEqual((handler, name), expected)
504 self.assertEqual(args, (req,))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000505
506 def test_handler_order(self):
507 o = OpenerDirector()
508 handlers = []
509 for meths, handler_order in [
510 ([("http_open", "return self")], 500),
511 (["http_open"], 0),
512 ]:
513 class MockHandlerSubclass(MockHandler): pass
514 h = MockHandlerSubclass(meths)
515 h.handler_order = handler_order
516 handlers.append(h)
517 o.add_handler(h)
518
519 r = o.open("http://example.com/")
520 # handlers called in reverse order, thanks to their sort order
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000521 self.assertEqual(o.calls[0][0], handlers[1])
522 self.assertEqual(o.calls[1][0], handlers[0])
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000523
524 def test_raise(self):
525 # raising URLError stops processing of request
526 o = OpenerDirector()
527 meth_spec = [
528 [("http_open", "raise")],
529 [("http_open", "return self")],
530 ]
531 handlers = add_ordered_mock_handlers(o, meth_spec)
532
533 req = Request("http://example.com/")
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000534 self.assertRaises(urllib.error.URLError, o.open, req)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000535 self.assertEqual(o.calls, [(handlers[0], "http_open", (req,), {})])
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000536
537## def test_error(self):
538## # XXX this doesn't actually seem to be used in standard library,
539## # but should really be tested anyway...
540
541 def test_http_error(self):
542 # XXX http_error_default
543 # http errors are a special case
544 o = OpenerDirector()
545 meth_spec = [
546 [("http_open", "error 302")],
547 [("http_error_400", "raise"), "http_open"],
548 [("http_error_302", "return response"), "http_error_303",
549 "http_error"],
550 [("http_error_302")],
551 ]
552 handlers = add_ordered_mock_handlers(o, meth_spec)
553
554 class Unknown:
555 def __eq__(self, other): return True
556
557 req = Request("http://example.com/")
558 r = o.open(req)
559 assert len(o.calls) == 2
560 calls = [(handlers[0], "http_open", (req,)),
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000561 (handlers[2], "http_error_302",
562 (req, Unknown(), 302, "", {}))]
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000563 for expected, got in zip(calls, o.calls):
564 handler, method_name, args = expected
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000565 self.assertEqual((handler, method_name), got[:2])
566 self.assertEqual(args, got[2])
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000567
568 def test_processors(self):
569 # *_request / *_response methods get called appropriately
570 o = OpenerDirector()
571 meth_spec = [
572 [("http_request", "return request"),
573 ("http_response", "return response")],
574 [("http_request", "return request"),
575 ("http_response", "return response")],
576 ]
577 handlers = add_ordered_mock_handlers(o, meth_spec)
578
579 req = Request("http://example.com/")
580 r = o.open(req)
581 # processor methods are called on *all* handlers that define them,
582 # not just the first handler that handles the request
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000583 calls = [
584 (handlers[0], "http_request"), (handlers[1], "http_request"),
585 (handlers[0], "http_response"), (handlers[1], "http_response")]
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000586
587 for i, (handler, name, args, kwds) in enumerate(o.calls):
588 if i < 2:
589 # *_request
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000590 self.assertEqual((handler, name), calls[i])
591 self.assertEqual(len(args), 1)
Georg Brandlab91fde2009-08-13 08:51:18 +0000592 self.assertTrue(isinstance(args[0], Request))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000593 else:
594 # *_response
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000595 self.assertEqual((handler, name), calls[i])
596 self.assertEqual(len(args), 2)
Georg Brandlab91fde2009-08-13 08:51:18 +0000597 self.assertTrue(isinstance(args[0], Request))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000598 # response from opener.open is None, because there's no
599 # handler that defines http_open to handle it
Georg Brandlab91fde2009-08-13 08:51:18 +0000600 self.assertTrue(args[1] is None or
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000601 isinstance(args[1], MockResponse))
602
603
Tim Peters58eb11c2004-01-18 20:29:55 +0000604def sanepathname2url(path):
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000605 urlpath = urllib.request.pathname2url(path)
Tim Peters58eb11c2004-01-18 20:29:55 +0000606 if os.name == "nt" and urlpath.startswith("///"):
607 urlpath = urlpath[2:]
608 # XXX don't ask me about the mac...
609 return urlpath
610
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000611class HandlerTests(unittest.TestCase):
612
613 def test_ftp(self):
614 class MockFTPWrapper:
615 def __init__(self, data): self.data = data
616 def retrfile(self, filename, filetype):
617 self.filename, self.filetype = filename, filetype
Guido van Rossum34d19282007-08-09 01:03:29 +0000618 return io.StringIO(self.data), len(self.data)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000619
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000620 class NullFTPHandler(urllib.request.FTPHandler):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000621 def __init__(self, data): self.data = data
Georg Brandlf78e02b2008-06-10 17:40:04 +0000622 def connect_ftp(self, user, passwd, host, port, dirs,
623 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000624 self.user, self.passwd = user, passwd
625 self.host, self.port = host, port
626 self.dirs = dirs
627 self.ftpwrapper = MockFTPWrapper(self.data)
628 return self.ftpwrapper
629
Georg Brandlf78e02b2008-06-10 17:40:04 +0000630 import ftplib
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000631 data = "rheum rhaponicum"
632 h = NullFTPHandler(data)
633 o = h.parent = MockOpener()
634
Senthil Kumaran723a7a62010-11-18 16:44:38 +0000635 for url, host, port, user, passwd, type_, dirs, filename, mimetype in [
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000636 ("ftp://localhost/foo/bar/baz.html",
Senthil Kumaran723a7a62010-11-18 16:44:38 +0000637 "localhost", ftplib.FTP_PORT, "", "", "I",
638 ["foo", "bar"], "baz.html", "text/html"),
639 ("ftp://parrot@localhost/foo/bar/baz.html",
640 "localhost", ftplib.FTP_PORT, "parrot", "", "I",
641 ["foo", "bar"], "baz.html", "text/html"),
642 ("ftp://%25parrot@localhost/foo/bar/baz.html",
643 "localhost", ftplib.FTP_PORT, "%parrot", "", "I",
644 ["foo", "bar"], "baz.html", "text/html"),
645 ("ftp://%2542parrot@localhost/foo/bar/baz.html",
646 "localhost", ftplib.FTP_PORT, "%42parrot", "", "I",
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000647 ["foo", "bar"], "baz.html", "text/html"),
Kurt B. Kaiser3f7cb5d2004-07-11 17:14:13 +0000648 ("ftp://localhost:80/foo/bar/",
Senthil Kumaran723a7a62010-11-18 16:44:38 +0000649 "localhost", 80, "", "", "D",
Kurt B. Kaiser3f7cb5d2004-07-11 17:14:13 +0000650 ["foo", "bar"], "", None),
651 ("ftp://localhost/baz.gif;type=a",
Senthil Kumaran723a7a62010-11-18 16:44:38 +0000652 "localhost", ftplib.FTP_PORT, "", "", "A",
Kurt B. Kaiser3f7cb5d2004-07-11 17:14:13 +0000653 [], "baz.gif", None), # XXX really this should guess image/gif
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000654 ]:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000655 req = Request(url)
656 req.timeout = None
657 r = h.ftp_open(req)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000658 # ftp authentication not yet implemented by FTPHandler
Senthil Kumaran723a7a62010-11-18 16:44:38 +0000659 self.assertEqual(h.user, user)
660 self.assertEqual(h.passwd, passwd)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000661 self.assertEqual(h.host, socket.gethostbyname(host))
662 self.assertEqual(h.port, port)
663 self.assertEqual(h.dirs, dirs)
664 self.assertEqual(h.ftpwrapper.filename, filename)
665 self.assertEqual(h.ftpwrapper.filetype, type_)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000666 headers = r.info()
Kurt B. Kaiser3f7cb5d2004-07-11 17:14:13 +0000667 self.assertEqual(headers.get("Content-type"), mimetype)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000668 self.assertEqual(int(headers["Content-length"]), len(data))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000669
670 def test_file(self):
Benjamin Petersona0c0a4a2008-06-12 22:15:50 +0000671 import email.utils, socket
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000672 h = urllib.request.FileHandler()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000673 o = h.parent = MockOpener()
674
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000675 TESTFN = support.TESTFN
Tim Peters58eb11c2004-01-18 20:29:55 +0000676 urlpath = sanepathname2url(os.path.abspath(TESTFN))
Guido van Rossum6a2ccd02007-07-16 20:51:57 +0000677 towrite = b"hello, world\n"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000678 urls = [
Tim Peters58eb11c2004-01-18 20:29:55 +0000679 "file://localhost%s" % urlpath,
680 "file://%s" % urlpath,
681 "file://%s%s" % (socket.gethostbyname('localhost'), urlpath),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000682 ]
683 try:
684 localaddr = socket.gethostbyname(socket.gethostname())
685 except socket.gaierror:
686 localaddr = ''
687 if localaddr:
688 urls.append("file://%s%s" % (localaddr, urlpath))
689
690 for url in urls:
Tim Peters58eb11c2004-01-18 20:29:55 +0000691 f = open(TESTFN, "wb")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000692 try:
693 try:
694 f.write(towrite)
695 finally:
696 f.close()
697
698 r = h.file_open(Request(url))
699 try:
700 data = r.read()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000701 headers = r.info()
Senthil Kumaran51964772010-05-08 03:31:56 +0000702 respurl = r.geturl()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000703 finally:
704 r.close()
Tim Peters58eb11c2004-01-18 20:29:55 +0000705 stats = os.stat(TESTFN)
Benjamin Petersona0c0a4a2008-06-12 22:15:50 +0000706 modified = email.utils.formatdate(stats.st_mtime, usegmt=True)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000707 finally:
708 os.remove(TESTFN)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000709 self.assertEqual(data, towrite)
710 self.assertEqual(headers["Content-type"], "text/plain")
711 self.assertEqual(headers["Content-length"], "13")
Tim Peters58eb11c2004-01-18 20:29:55 +0000712 self.assertEqual(headers["Last-modified"], modified)
Senthil Kumaran51964772010-05-08 03:31:56 +0000713 self.assertEqual(respurl, url)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000714
715 for url in [
Tim Peters58eb11c2004-01-18 20:29:55 +0000716 "file://localhost:80%s" % urlpath,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000717 "file:///file_does_not_exist.txt",
718 "file://%s:80%s/%s" % (socket.gethostbyname('localhost'),
719 os.getcwd(), TESTFN),
720 "file://somerandomhost.ontheinternet.com%s/%s" %
721 (os.getcwd(), TESTFN),
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000722 ]:
723 try:
Tim Peters58eb11c2004-01-18 20:29:55 +0000724 f = open(TESTFN, "wb")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000725 try:
726 f.write(towrite)
727 finally:
728 f.close()
729
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000730 self.assertRaises(urllib.error.URLError,
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000731 h.file_open, Request(url))
732 finally:
733 os.remove(TESTFN)
734
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000735 h = urllib.request.FileHandler()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000736 o = h.parent = MockOpener()
737 # XXXX why does // mean ftp (and /// mean not ftp!), and where
738 # is file: scheme specified? I think this is really a bug, and
739 # what was intended was to distinguish between URLs like:
740 # file:/blah.txt (a file)
741 # file://localhost/blah.txt (a file)
742 # file:///blah.txt (a file)
743 # file://ftp.example.com/blah.txt (an ftp URL)
744 for url, ftp in [
745 ("file://ftp.example.com//foo.txt", True),
746 ("file://ftp.example.com///foo.txt", False),
747# XXXX bug: fails with OSError, should be URLError
748 ("file://ftp.example.com/foo.txt", False),
Senthil Kumaran34024142010-07-11 03:15:25 +0000749 ("file://somehost//foo/something.txt", True),
750 ("file://localhost//foo/something.txt", False),
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000751 ]:
752 req = Request(url)
753 try:
754 h.file_open(req)
755 # XXXX remove OSError when bug fixed
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000756 except (urllib.error.URLError, OSError):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000757 self.assertFalse(ftp)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000758 else:
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000759 self.assertIs(o.req, req)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000760 self.assertEqual(req.type, "ftp")
Benjamin Petersonecb6e812011-01-12 19:29:51 +0000761 self.assertEqual(req.type == "ftp", ftp)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000762
763 def test_http(self):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000764
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000765 h = urllib.request.AbstractHTTPHandler()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000766 o = h.parent = MockOpener()
767
768 url = "http://example.com/"
769 for method, data in [("GET", None), ("POST", "blah")]:
770 req = Request(url, data, {"Foo": "bar"})
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000771 req.timeout = None
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000772 req.add_unredirected_header("Spam", "eggs")
773 http = MockHTTPClass()
774 r = h.do_open(http, req)
775
776 # result attributes
777 r.read; r.readline # wrapped MockFile methods
778 r.info; r.geturl # addinfourl methods
779 r.code, r.msg == 200, "OK" # added from MockHTTPClass.getreply()
780 hdrs = r.info()
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000781 hdrs.get; hdrs.__contains__ # r.info() gives dict from .getreply()
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000782 self.assertEqual(r.geturl(), url)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000783
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000784 self.assertEqual(http.host, "example.com")
785 self.assertEqual(http.level, 0)
786 self.assertEqual(http.method, method)
787 self.assertEqual(http.selector, "/")
788 self.assertEqual(http.req_headers,
Jeremy Hyltonb3ee6f92004-02-24 19:40:35 +0000789 [("Connection", "close"),
790 ("Foo", "bar"), ("Spam", "eggs")])
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000791 self.assertEqual(http.data, data)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000792
793 # check socket.error converted to URLError
794 http.raise_on_endheaders = True
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000795 self.assertRaises(urllib.error.URLError, h.do_open, http, req)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000796
797 # check adding of standard headers
798 o.addheaders = [("Spam", "eggs")]
799 for data in "", None: # POST, GET
800 req = Request("http://example.com/", data)
801 r = MockResponse(200, "OK", {}, "")
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000802 newreq = h.do_request_(req)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000803 if data is None: # GET
Georg Brandlab91fde2009-08-13 08:51:18 +0000804 self.assertTrue("Content-length" not in req.unredirected_hdrs)
805 self.assertTrue("Content-type" not in req.unredirected_hdrs)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000806 else: # POST
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000807 self.assertEqual(req.unredirected_hdrs["Content-length"], "0")
808 self.assertEqual(req.unredirected_hdrs["Content-type"],
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000809 "application/x-www-form-urlencoded")
810 # XXX the details of Host could be better tested
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000811 self.assertEqual(req.unredirected_hdrs["Host"], "example.com")
812 self.assertEqual(req.unredirected_hdrs["Spam"], "eggs")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000813
814 # don't clobber existing headers
815 req.add_unredirected_header("Content-length", "foo")
816 req.add_unredirected_header("Content-type", "bar")
817 req.add_unredirected_header("Host", "baz")
818 req.add_unredirected_header("Spam", "foo")
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000819 newreq = h.do_request_(req)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000820 self.assertEqual(req.unredirected_hdrs["Content-length"], "foo")
821 self.assertEqual(req.unredirected_hdrs["Content-type"], "bar")
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000822 self.assertEqual(req.unredirected_hdrs["Host"], "baz")
823 self.assertEqual(req.unredirected_hdrs["Spam"], "foo")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000824
Facundo Batista72dc1ea2008-08-16 14:44:32 +0000825 def test_http_doubleslash(self):
826 # Checks the presence of any unnecessary double slash in url does not
827 # break anything. Previously, a double slash directly after the host
828 # could could cause incorrect parsing.
829 h = urllib.request.AbstractHTTPHandler()
830 o = h.parent = MockOpener()
831
832 data = ""
833 ds_urls = [
834 "http://example.com/foo/bar/baz.html",
835 "http://example.com//foo/bar/baz.html",
836 "http://example.com/foo//bar/baz.html",
837 "http://example.com/foo/bar//baz.html"
838 ]
839
840 for ds_url in ds_urls:
841 ds_req = Request(ds_url, data)
842
843 # Check whether host is determined correctly if there is no proxy
844 np_ds_req = h.do_request_(ds_req)
845 self.assertEqual(np_ds_req.unredirected_hdrs["Host"],"example.com")
846
847 # Check whether host is determined correctly if there is a proxy
848 ds_req.set_proxy("someproxy:3128",None)
849 p_ds_req = h.do_request_(ds_req)
850 self.assertEqual(p_ds_req.unredirected_hdrs["Host"],"example.com")
851
Senthil Kumarand17ebdb2010-11-22 04:53:57 +0000852 def test_fixpath_in_weirdurls(self):
853 # Issue4493: urllib2 to supply '/' when to urls where path does not
854 # start with'/'
855
856 h = urllib.request.AbstractHTTPHandler()
857 o = h.parent = MockOpener()
858
859 weird_url = 'http://www.python.org?getspam'
860 req = Request(weird_url)
861 newreq = h.do_request_(req)
862 self.assertEqual(newreq.host,'www.python.org')
863 self.assertEqual(newreq.selector,'/?getspam')
864
865 url_without_path = 'http://www.python.org'
866 req = Request(url_without_path)
867 newreq = h.do_request_(req)
868 self.assertEqual(newreq.host,'www.python.org')
869 self.assertEqual(newreq.selector,'')
870
Facundo Batista72dc1ea2008-08-16 14:44:32 +0000871
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000872 def test_errors(self):
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000873 h = urllib.request.HTTPErrorProcessor()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000874 o = h.parent = MockOpener()
875
876 url = "http://example.com/"
877 req = Request(url)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000878 # all 2xx are passed through
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000879 r = MockResponse(200, "OK", {}, "", url)
880 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000881 self.assertIs(r, newr)
882 self.assertFalse(hasattr(o, "proto")) # o.error not called
Guido van Rossumd8faa362007-04-27 19:54:29 +0000883 r = MockResponse(202, "Accepted", {}, "", url)
884 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000885 self.assertIs(r, newr)
886 self.assertFalse(hasattr(o, "proto")) # o.error not called
Guido van Rossumd8faa362007-04-27 19:54:29 +0000887 r = MockResponse(206, "Partial content", {}, "", url)
888 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000889 self.assertIs(r, newr)
890 self.assertFalse(hasattr(o, "proto")) # o.error not called
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000891 # anything else calls o.error (and MockOpener returns None, here)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000892 r = MockResponse(502, "Bad gateway", {}, "", url)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000893 self.assertIsNone(h.http_response(req, r))
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000894 self.assertEqual(o.proto, "http") # o.error called
Guido van Rossumd8faa362007-04-27 19:54:29 +0000895 self.assertEqual(o.args, (req, r, 502, "Bad gateway", {}))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000896
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000897 def test_cookies(self):
898 cj = MockCookieJar()
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000899 h = urllib.request.HTTPCookieProcessor(cj)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000900 o = h.parent = MockOpener()
901
902 req = Request("http://example.com/")
903 r = MockResponse(200, "OK", {}, "")
904 newreq = h.http_request(req)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000905 self.assertIs(cj.ach_req, req)
906 self.assertIs(cj.ach_req, newreq)
907 self.assertEqual(req.get_origin_req_host(), "example.com")
908 self.assertFalse(req.is_unverifiable())
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000909 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000910 self.assertIs(cj.ec_req, req)
911 self.assertIs(cj.ec_r, r)
912 self.assertIs(r, newr)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000913
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000914 def test_redirect(self):
915 from_url = "http://example.com/a.html"
916 to_url = "http://example.com/b.html"
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000917 h = urllib.request.HTTPRedirectHandler()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000918 o = h.parent = MockOpener()
919
920 # ordinary redirect behaviour
921 for code in 301, 302, 303, 307:
922 for data in None, "blah\nblah\n":
923 method = getattr(h, "http_error_%s" % code)
924 req = Request(from_url, data)
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000925 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000926 req.add_header("Nonsense", "viking=withhold")
Christian Heimes77c02eb2008-02-09 02:18:51 +0000927 if data is not None:
928 req.add_header("Content-Length", str(len(data)))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000929 req.add_unredirected_header("Spam", "spam")
930 try:
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000931 method(req, MockFile(), code, "Blah",
932 MockHeaders({"location": to_url}))
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000933 except urllib.error.HTTPError:
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000934 # 307 in response to POST requires user OK
Georg Brandlab91fde2009-08-13 08:51:18 +0000935 self.assertTrue(code == 307 and data is not None)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000936 self.assertEqual(o.req.get_full_url(), to_url)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000937 try:
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000938 self.assertEqual(o.req.get_method(), "GET")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000939 except AttributeError:
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000940 self.assertFalse(o.req.has_data())
Christian Heimes77c02eb2008-02-09 02:18:51 +0000941
942 # now it's a GET, there should not be headers regarding content
943 # (possibly dragged from before being a POST)
944 headers = [x.lower() for x in o.req.headers]
945 self.assertTrue("content-length" not in headers)
946 self.assertTrue("content-type" not in headers)
947
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000948 self.assertEqual(o.req.headers["Nonsense"],
949 "viking=withhold")
Georg Brandlab91fde2009-08-13 08:51:18 +0000950 self.assertTrue("Spam" not in o.req.headers)
951 self.assertTrue("Spam" not in o.req.unredirected_hdrs)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000952
953 # loop detection
954 req = Request(from_url)
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000955 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000956 def redirect(h, req, url=to_url):
957 h.http_error_302(req, MockFile(), 302, "Blah",
958 MockHeaders({"location": url}))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000959 # Note that the *original* request shares the same record of
960 # redirections with the sub-requests caused by the redirections.
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000961
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000962 # detect infinite loop redirect of a URL to itself
963 req = Request(from_url, origin_req_host="example.com")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000964 count = 0
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000965 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000966 try:
967 while 1:
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000968 redirect(h, req, "http://example.com/")
969 count = count + 1
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000970 except urllib.error.HTTPError:
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000971 # don't stop until max_repeats, because cookies may introduce state
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000972 self.assertEqual(count, urllib.request.HTTPRedirectHandler.max_repeats)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000973
974 # detect endless non-repeating chain of redirects
975 req = Request(from_url, origin_req_host="example.com")
976 count = 0
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000977 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000978 try:
979 while 1:
980 redirect(h, req, "http://example.com/%d" % count)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000981 count = count + 1
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000982 except urllib.error.HTTPError:
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000983 self.assertEqual(count,
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000984 urllib.request.HTTPRedirectHandler.max_redirections)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000985
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000986 def test_cookie_redirect(self):
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000987 # cookies shouldn't leak into redirected requests
Georg Brandl24420152008-05-26 16:32:26 +0000988 from http.cookiejar import CookieJar
989 from test.test_http_cookiejar import interact_netscape
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000990
991 cj = CookieJar()
992 interact_netscape(cj, "http://www.example.com/", "spam=eggs")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000993 hh = MockHTTPHandler(302, "Location: http://www.cracker.com/\r\n\r\n")
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000994 hdeh = urllib.request.HTTPDefaultErrorHandler()
995 hrh = urllib.request.HTTPRedirectHandler()
996 cp = urllib.request.HTTPCookieProcessor(cj)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000997 o = build_test_opener(hh, hdeh, hrh, cp)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000998 o.open("http://www.example.com/")
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000999 self.assertFalse(hh.req.has_header("Cookie"))
Martin v. Löwis2a6ba902004-05-31 18:22:40 +00001000
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001001 def test_proxy(self):
1002 o = OpenerDirector()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001003 ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001004 o.add_handler(ph)
1005 meth_spec = [
1006 [("http_open", "return response")]
1007 ]
1008 handlers = add_ordered_mock_handlers(o, meth_spec)
1009
1010 req = Request("http://acme.example.com/")
1011 self.assertEqual(req.get_host(), "acme.example.com")
1012 r = o.open(req)
1013 self.assertEqual(req.get_host(), "proxy.example.com:3128")
1014
1015 self.assertEqual([(handlers[0], "http_open")],
1016 [tup[0:2] for tup in o.calls])
1017
Senthil Kumaran11301632009-10-11 06:07:46 +00001018 def test_proxy_no_proxy(self):
1019 os.environ['no_proxy'] = 'python.org'
1020 o = OpenerDirector()
1021 ph = urllib.request.ProxyHandler(dict(http="proxy.example.com"))
1022 o.add_handler(ph)
1023 req = Request("http://www.perl.org/")
1024 self.assertEqual(req.get_host(), "www.perl.org")
1025 r = o.open(req)
1026 self.assertEqual(req.get_host(), "proxy.example.com")
1027 req = Request("http://www.python.org")
1028 self.assertEqual(req.get_host(), "www.python.org")
1029 r = o.open(req)
1030 self.assertEqual(req.get_host(), "www.python.org")
1031 del os.environ['no_proxy']
1032
1033
Senthil Kumaran0ac1f832009-07-26 12:39:47 +00001034 def test_proxy_https(self):
1035 o = OpenerDirector()
1036 ph = urllib.request.ProxyHandler(dict(https="proxy.example.com:3128"))
1037 o.add_handler(ph)
1038 meth_spec = [
1039 [("https_open", "return response")]
1040 ]
1041 handlers = add_ordered_mock_handlers(o, meth_spec)
1042
1043 req = Request("https://www.example.com/")
1044 self.assertEqual(req.get_host(), "www.example.com")
1045 r = o.open(req)
1046 self.assertEqual(req.get_host(), "proxy.example.com:3128")
1047 self.assertEqual([(handlers[0], "https_open")],
1048 [tup[0:2] for tup in o.calls])
1049
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +00001050 def test_proxy_https_proxy_authorization(self):
1051 o = OpenerDirector()
1052 ph = urllib.request.ProxyHandler(dict(https='proxy.example.com:3128'))
1053 o.add_handler(ph)
1054 https_handler = MockHTTPSHandler()
1055 o.add_handler(https_handler)
1056 req = Request("https://www.example.com/")
1057 req.add_header("Proxy-Authorization","FooBar")
1058 req.add_header("User-Agent","Grail")
1059 self.assertEqual(req.get_host(), "www.example.com")
1060 self.assertIsNone(req._tunnel_host)
1061 r = o.open(req)
1062 # Verify Proxy-Authorization gets tunneled to request.
1063 # httpsconn req_headers do not have the Proxy-Authorization header but
1064 # the req will have.
1065 self.assertFalse(("Proxy-Authorization","FooBar") in
1066 https_handler.httpconn.req_headers)
1067 self.assertTrue(("User-Agent","Grail") in
1068 https_handler.httpconn.req_headers)
1069 self.assertIsNotNone(req._tunnel_host)
1070 self.assertEqual(req.get_host(), "proxy.example.com:3128")
1071 self.assertEqual(req.get_header("Proxy-authorization"),"FooBar")
Senthil Kumaran0ac1f832009-07-26 12:39:47 +00001072
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001073 def test_basic_auth(self, quote_char='"'):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001074 opener = OpenerDirector()
1075 password_manager = MockPasswordManager()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001076 auth_handler = urllib.request.HTTPBasicAuthHandler(password_manager)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001077 realm = "ACME Widget Store"
1078 http_handler = MockHTTPHandler(
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001079 401, 'WWW-Authenticate: Basic realm=%s%s%s\r\n\r\n' %
1080 (quote_char, realm, quote_char) )
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001081 opener.add_handler(auth_handler)
1082 opener.add_handler(http_handler)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001083 self._test_basic_auth(opener, auth_handler, "Authorization",
1084 realm, http_handler, password_manager,
1085 "http://acme.example.com/protected",
1086 "http://acme.example.com/protected",
1087 )
1088
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001089 def test_basic_auth_with_single_quoted_realm(self):
1090 self.test_basic_auth(quote_char="'")
1091
Thomas Wouters477c8d52006-05-27 19:21:47 +00001092 def test_proxy_basic_auth(self):
1093 opener = OpenerDirector()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001094 ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
Thomas Wouters477c8d52006-05-27 19:21:47 +00001095 opener.add_handler(ph)
1096 password_manager = MockPasswordManager()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001097 auth_handler = urllib.request.ProxyBasicAuthHandler(password_manager)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001098 realm = "ACME Networks"
1099 http_handler = MockHTTPHandler(
1100 407, 'Proxy-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001101 opener.add_handler(auth_handler)
1102 opener.add_handler(http_handler)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001103 self._test_basic_auth(opener, auth_handler, "Proxy-authorization",
Thomas Wouters477c8d52006-05-27 19:21:47 +00001104 realm, http_handler, password_manager,
1105 "http://acme.example.com:3128/protected",
1106 "proxy.example.com:3128",
1107 )
1108
1109 def test_basic_and_digest_auth_handlers(self):
1110 # HTTPDigestAuthHandler threw an exception if it couldn't handle a 40*
1111 # response (http://python.org/sf/1479302), where it should instead
1112 # return None to allow another handler (especially
1113 # HTTPBasicAuthHandler) to handle the response.
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001114
1115 # Also (http://python.org/sf/14797027, RFC 2617 section 1.2), we must
1116 # try digest first (since it's the strongest auth scheme), so we record
1117 # order of calls here to check digest comes first:
1118 class RecordingOpenerDirector(OpenerDirector):
1119 def __init__(self):
1120 OpenerDirector.__init__(self)
1121 self.recorded = []
1122 def record(self, info):
1123 self.recorded.append(info)
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001124 class TestDigestAuthHandler(urllib.request.HTTPDigestAuthHandler):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001125 def http_error_401(self, *args, **kwds):
1126 self.parent.record("digest")
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001127 urllib.request.HTTPDigestAuthHandler.http_error_401(self,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001128 *args, **kwds)
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001129 class TestBasicAuthHandler(urllib.request.HTTPBasicAuthHandler):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001130 def http_error_401(self, *args, **kwds):
1131 self.parent.record("basic")
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001132 urllib.request.HTTPBasicAuthHandler.http_error_401(self,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001133 *args, **kwds)
1134
1135 opener = RecordingOpenerDirector()
Thomas Wouters477c8d52006-05-27 19:21:47 +00001136 password_manager = MockPasswordManager()
1137 digest_handler = TestDigestAuthHandler(password_manager)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001138 basic_handler = TestBasicAuthHandler(password_manager)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001139 realm = "ACME Networks"
1140 http_handler = MockHTTPHandler(
1141 401, 'WWW-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001142 opener.add_handler(basic_handler)
1143 opener.add_handler(digest_handler)
1144 opener.add_handler(http_handler)
1145
1146 # check basic auth isn't blocked by digest handler failing
Thomas Wouters477c8d52006-05-27 19:21:47 +00001147 self._test_basic_auth(opener, basic_handler, "Authorization",
1148 realm, http_handler, password_manager,
1149 "http://acme.example.com/protected",
1150 "http://acme.example.com/protected",
1151 )
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001152 # check digest was tried before basic (twice, because
1153 # _test_basic_auth called .open() twice)
1154 self.assertEqual(opener.recorded, ["digest", "basic"]*2)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001155
1156 def _test_basic_auth(self, opener, auth_handler, auth_header,
1157 realm, http_handler, password_manager,
1158 request_url, protected_url):
Christian Heimes05e8be12008-02-23 18:30:17 +00001159 import base64
Thomas Wouters477c8d52006-05-27 19:21:47 +00001160 user, password = "wile", "coyote"
Thomas Wouters477c8d52006-05-27 19:21:47 +00001161
1162 # .add_password() fed through to password manager
1163 auth_handler.add_password(realm, request_url, user, password)
1164 self.assertEqual(realm, password_manager.realm)
1165 self.assertEqual(request_url, password_manager.url)
1166 self.assertEqual(user, password_manager.user)
1167 self.assertEqual(password, password_manager.password)
1168
1169 r = opener.open(request_url)
1170
1171 # should have asked the password manager for the username/password
1172 self.assertEqual(password_manager.target_realm, realm)
1173 self.assertEqual(password_manager.target_url, protected_url)
1174
1175 # expect one request without authorization, then one with
1176 self.assertEqual(len(http_handler.requests), 2)
1177 self.assertFalse(http_handler.requests[0].has_header(auth_header))
Guido van Rossum98b349f2007-08-27 21:47:52 +00001178 userpass = bytes('%s:%s' % (user, password), "ascii")
Guido van Rossum98297ee2007-11-06 21:34:58 +00001179 auth_hdr_value = ('Basic ' +
Georg Brandl706824f2009-06-04 09:42:55 +00001180 base64.encodebytes(userpass).strip().decode())
Thomas Wouters477c8d52006-05-27 19:21:47 +00001181 self.assertEqual(http_handler.requests[1].get_header(auth_header),
1182 auth_hdr_value)
Senthil Kumaranefcd8832010-02-24 16:56:20 +00001183 self.assertEqual(http_handler.requests[1].unredirected_hdrs[auth_header],
1184 auth_hdr_value)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001185 # if the password manager can't find a password, the handler won't
1186 # handle the HTTP auth error
1187 password_manager.user = password_manager.password = None
1188 http_handler.reset()
1189 r = opener.open(request_url)
1190 self.assertEqual(len(http_handler.requests), 1)
1191 self.assertFalse(http_handler.requests[0].has_header(auth_header))
1192
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001193class MiscTests(unittest.TestCase):
1194
1195 def test_build_opener(self):
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001196 class MyHTTPHandler(urllib.request.HTTPHandler): pass
1197 class FooHandler(urllib.request.BaseHandler):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001198 def foo_open(self): pass
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001199 class BarHandler(urllib.request.BaseHandler):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001200 def bar_open(self): pass
1201
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001202 build_opener = urllib.request.build_opener
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001203
1204 o = build_opener(FooHandler, BarHandler)
1205 self.opener_has_handler(o, FooHandler)
1206 self.opener_has_handler(o, BarHandler)
1207
1208 # can take a mix of classes and instances
1209 o = build_opener(FooHandler, BarHandler())
1210 self.opener_has_handler(o, FooHandler)
1211 self.opener_has_handler(o, BarHandler)
1212
1213 # subclasses of default handlers override default handlers
1214 o = build_opener(MyHTTPHandler)
1215 self.opener_has_handler(o, MyHTTPHandler)
1216
1217 # a particular case of overriding: default handlers can be passed
1218 # in explicitly
1219 o = build_opener()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001220 self.opener_has_handler(o, urllib.request.HTTPHandler)
1221 o = build_opener(urllib.request.HTTPHandler)
1222 self.opener_has_handler(o, urllib.request.HTTPHandler)
1223 o = build_opener(urllib.request.HTTPHandler())
1224 self.opener_has_handler(o, urllib.request.HTTPHandler)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001225
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001226 # Issue2670: multiple handlers sharing the same base class
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001227 class MyOtherHTTPHandler(urllib.request.HTTPHandler): pass
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001228 o = build_opener(MyHTTPHandler, MyOtherHTTPHandler)
1229 self.opener_has_handler(o, MyHTTPHandler)
1230 self.opener_has_handler(o, MyOtherHTTPHandler)
1231
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001232 def opener_has_handler(self, opener, handler_class):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +00001233 self.assertTrue(any(h.__class__ == handler_class
1234 for h in opener.handlers))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001235
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001236class RequestTests(unittest.TestCase):
1237
1238 def setUp(self):
1239 self.get = Request("http://www.python.org/~jeremy/")
1240 self.post = Request("http://www.python.org/~jeremy/",
1241 "data",
1242 headers={"X-Test": "test"})
1243
1244 def test_method(self):
1245 self.assertEqual("POST", self.post.get_method())
1246 self.assertEqual("GET", self.get.get_method())
1247
1248 def test_add_data(self):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +00001249 self.assertFalse(self.get.has_data())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001250 self.assertEqual("GET", self.get.get_method())
1251 self.get.add_data("spam")
Georg Brandlab91fde2009-08-13 08:51:18 +00001252 self.assertTrue(self.get.has_data())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001253 self.assertEqual("POST", self.get.get_method())
1254
1255 def test_get_full_url(self):
1256 self.assertEqual("http://www.python.org/~jeremy/",
1257 self.get.get_full_url())
1258
1259 def test_selector(self):
1260 self.assertEqual("/~jeremy/", self.get.get_selector())
1261 req = Request("http://www.python.org/")
1262 self.assertEqual("/", req.get_selector())
1263
1264 def test_get_type(self):
1265 self.assertEqual("http", self.get.get_type())
1266
1267 def test_get_host(self):
1268 self.assertEqual("www.python.org", self.get.get_host())
1269
1270 def test_get_host_unquote(self):
1271 req = Request("http://www.%70ython.org/")
1272 self.assertEqual("www.python.org", req.get_host())
1273
1274 def test_proxy(self):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +00001275 self.assertFalse(self.get.has_proxy())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001276 self.get.set_proxy("www.perl.org", "http")
Georg Brandlab91fde2009-08-13 08:51:18 +00001277 self.assertTrue(self.get.has_proxy())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001278 self.assertEqual("www.python.org", self.get.get_origin_req_host())
1279 self.assertEqual("www.perl.org", self.get.get_host())
1280
Senthil Kumaran4c88db72010-08-08 11:30:58 +00001281 def test_wrapped_url(self):
1282 req = Request("<URL:http://www.python.org>")
1283 self.assertEqual("www.python.org", req.get_host())
1284
1285 def test_urlwith_fragment(self):
1286 req = Request("http://www.python.org/?qs=query#fragment=true")
1287 self.assertEqual("/?qs=query", req.get_selector())
1288 req = Request("http://www.python.org/#fun=true")
1289 self.assertEqual("/", req.get_selector())
1290
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001291
1292def test_main(verbose=None):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001293 from test import test_urllib2
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001294 support.run_doctest(test_urllib2, verbose)
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001295 support.run_doctest(urllib.request, verbose)
Andrew M. Kuchlingbd3200f2004-06-29 13:15:46 +00001296 tests = (TrivialTests,
1297 OpenerDirectorTests,
1298 HandlerTests,
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001299 MiscTests,
1300 RequestTests)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001301 support.run_unittest(*tests)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001302
1303if __name__ == "__main__":
1304 test_main(verbose=True)