blob: 38cf607bb9d84809a87c679590f343cd80fe9e7c [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")
Senthil Kumaran34024142010-07-11 03:15:25 +0000761 self.assertEqual(req.type is "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
852
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000853 def test_errors(self):
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000854 h = urllib.request.HTTPErrorProcessor()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000855 o = h.parent = MockOpener()
856
857 url = "http://example.com/"
858 req = Request(url)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000859 # all 2xx are passed through
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000860 r = MockResponse(200, "OK", {}, "", url)
861 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000862 self.assertIs(r, newr)
863 self.assertFalse(hasattr(o, "proto")) # o.error not called
Guido van Rossumd8faa362007-04-27 19:54:29 +0000864 r = MockResponse(202, "Accepted", {}, "", url)
865 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000866 self.assertIs(r, newr)
867 self.assertFalse(hasattr(o, "proto")) # o.error not called
Guido van Rossumd8faa362007-04-27 19:54:29 +0000868 r = MockResponse(206, "Partial content", {}, "", url)
869 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000870 self.assertIs(r, newr)
871 self.assertFalse(hasattr(o, "proto")) # o.error not called
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000872 # anything else calls o.error (and MockOpener returns None, here)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000873 r = MockResponse(502, "Bad gateway", {}, "", url)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000874 self.assertIsNone(h.http_response(req, r))
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000875 self.assertEqual(o.proto, "http") # o.error called
Guido van Rossumd8faa362007-04-27 19:54:29 +0000876 self.assertEqual(o.args, (req, r, 502, "Bad gateway", {}))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000877
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000878 def test_cookies(self):
879 cj = MockCookieJar()
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000880 h = urllib.request.HTTPCookieProcessor(cj)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000881 o = h.parent = MockOpener()
882
883 req = Request("http://example.com/")
884 r = MockResponse(200, "OK", {}, "")
885 newreq = h.http_request(req)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000886 self.assertIs(cj.ach_req, req)
887 self.assertIs(cj.ach_req, newreq)
888 self.assertEqual(req.get_origin_req_host(), "example.com")
889 self.assertFalse(req.is_unverifiable())
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000890 newr = h.http_response(req, r)
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000891 self.assertIs(cj.ec_req, req)
892 self.assertIs(cj.ec_r, r)
893 self.assertIs(r, newr)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000894
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000895 def test_redirect(self):
896 from_url = "http://example.com/a.html"
897 to_url = "http://example.com/b.html"
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000898 h = urllib.request.HTTPRedirectHandler()
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000899 o = h.parent = MockOpener()
900
901 # ordinary redirect behaviour
902 for code in 301, 302, 303, 307:
903 for data in None, "blah\nblah\n":
904 method = getattr(h, "http_error_%s" % code)
905 req = Request(from_url, data)
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000906 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000907 req.add_header("Nonsense", "viking=withhold")
Christian Heimes77c02eb2008-02-09 02:18:51 +0000908 if data is not None:
909 req.add_header("Content-Length", str(len(data)))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000910 req.add_unredirected_header("Spam", "spam")
911 try:
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000912 method(req, MockFile(), code, "Blah",
913 MockHeaders({"location": to_url}))
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000914 except urllib.error.HTTPError:
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000915 # 307 in response to POST requires user OK
Georg Brandlab91fde2009-08-13 08:51:18 +0000916 self.assertTrue(code == 307 and data is not None)
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000917 self.assertEqual(o.req.get_full_url(), to_url)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000918 try:
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000919 self.assertEqual(o.req.get_method(), "GET")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000920 except AttributeError:
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000921 self.assertFalse(o.req.has_data())
Christian Heimes77c02eb2008-02-09 02:18:51 +0000922
923 # now it's a GET, there should not be headers regarding content
924 # (possibly dragged from before being a POST)
925 headers = [x.lower() for x in o.req.headers]
926 self.assertTrue("content-length" not in headers)
927 self.assertTrue("content-type" not in headers)
928
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000929 self.assertEqual(o.req.headers["Nonsense"],
930 "viking=withhold")
Georg Brandlab91fde2009-08-13 08:51:18 +0000931 self.assertTrue("Spam" not in o.req.headers)
932 self.assertTrue("Spam" not in o.req.unredirected_hdrs)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000933
934 # loop detection
935 req = Request(from_url)
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000936 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000937 def redirect(h, req, url=to_url):
938 h.http_error_302(req, MockFile(), 302, "Blah",
939 MockHeaders({"location": url}))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000940 # Note that the *original* request shares the same record of
941 # redirections with the sub-requests caused by the redirections.
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000942
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000943 # detect infinite loop redirect of a URL to itself
944 req = Request(from_url, origin_req_host="example.com")
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000945 count = 0
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000946 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000947 try:
948 while 1:
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000949 redirect(h, req, "http://example.com/")
950 count = count + 1
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000951 except urllib.error.HTTPError:
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000952 # don't stop until max_repeats, because cookies may introduce state
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000953 self.assertEqual(count, urllib.request.HTTPRedirectHandler.max_repeats)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000954
955 # detect endless non-repeating chain of redirects
956 req = Request(from_url, origin_req_host="example.com")
957 count = 0
Senthil Kumarane9da06f2009-07-19 04:20:12 +0000958 req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000959 try:
960 while 1:
961 redirect(h, req, "http://example.com/%d" % count)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000962 count = count + 1
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000963 except urllib.error.HTTPError:
Jeremy Hyltondf38ea92003-12-17 20:42:38 +0000964 self.assertEqual(count,
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000965 urllib.request.HTTPRedirectHandler.max_redirections)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +0000966
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000967 def test_cookie_redirect(self):
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000968 # cookies shouldn't leak into redirected requests
Georg Brandl24420152008-05-26 16:32:26 +0000969 from http.cookiejar import CookieJar
970 from test.test_http_cookiejar import interact_netscape
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000971
972 cj = CookieJar()
973 interact_netscape(cj, "http://www.example.com/", "spam=eggs")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000974 hh = MockHTTPHandler(302, "Location: http://www.cracker.com/\r\n\r\n")
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000975 hdeh = urllib.request.HTTPDefaultErrorHandler()
976 hrh = urllib.request.HTTPRedirectHandler()
977 cp = urllib.request.HTTPCookieProcessor(cj)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000978 o = build_test_opener(hh, hdeh, hrh, cp)
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000979 o.open("http://www.example.com/")
Florent Xiclunab4efb3d2010-08-14 18:24:40 +0000980 self.assertFalse(hh.req.has_header("Cookie"))
Martin v. Löwis2a6ba902004-05-31 18:22:40 +0000981
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000982 def test_proxy(self):
983 o = OpenerDirector()
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000984 ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000985 o.add_handler(ph)
986 meth_spec = [
987 [("http_open", "return response")]
988 ]
989 handlers = add_ordered_mock_handlers(o, meth_spec)
990
991 req = Request("http://acme.example.com/")
992 self.assertEqual(req.get_host(), "acme.example.com")
993 r = o.open(req)
994 self.assertEqual(req.get_host(), "proxy.example.com:3128")
995
996 self.assertEqual([(handlers[0], "http_open")],
997 [tup[0:2] for tup in o.calls])
998
Senthil Kumaran11301632009-10-11 06:07:46 +0000999 def test_proxy_no_proxy(self):
1000 os.environ['no_proxy'] = 'python.org'
1001 o = OpenerDirector()
1002 ph = urllib.request.ProxyHandler(dict(http="proxy.example.com"))
1003 o.add_handler(ph)
1004 req = Request("http://www.perl.org/")
1005 self.assertEqual(req.get_host(), "www.perl.org")
1006 r = o.open(req)
1007 self.assertEqual(req.get_host(), "proxy.example.com")
1008 req = Request("http://www.python.org")
1009 self.assertEqual(req.get_host(), "www.python.org")
1010 r = o.open(req)
1011 self.assertEqual(req.get_host(), "www.python.org")
1012 del os.environ['no_proxy']
1013
1014
Senthil Kumaran0ac1f832009-07-26 12:39:47 +00001015 def test_proxy_https(self):
1016 o = OpenerDirector()
1017 ph = urllib.request.ProxyHandler(dict(https="proxy.example.com:3128"))
1018 o.add_handler(ph)
1019 meth_spec = [
1020 [("https_open", "return response")]
1021 ]
1022 handlers = add_ordered_mock_handlers(o, meth_spec)
1023
1024 req = Request("https://www.example.com/")
1025 self.assertEqual(req.get_host(), "www.example.com")
1026 r = o.open(req)
1027 self.assertEqual(req.get_host(), "proxy.example.com:3128")
1028 self.assertEqual([(handlers[0], "https_open")],
1029 [tup[0:2] for tup in o.calls])
1030
Senthil Kumaran4b9fbeb2009-12-20 07:18:22 +00001031 def test_proxy_https_proxy_authorization(self):
1032 o = OpenerDirector()
1033 ph = urllib.request.ProxyHandler(dict(https='proxy.example.com:3128'))
1034 o.add_handler(ph)
1035 https_handler = MockHTTPSHandler()
1036 o.add_handler(https_handler)
1037 req = Request("https://www.example.com/")
1038 req.add_header("Proxy-Authorization","FooBar")
1039 req.add_header("User-Agent","Grail")
1040 self.assertEqual(req.get_host(), "www.example.com")
1041 self.assertIsNone(req._tunnel_host)
1042 r = o.open(req)
1043 # Verify Proxy-Authorization gets tunneled to request.
1044 # httpsconn req_headers do not have the Proxy-Authorization header but
1045 # the req will have.
1046 self.assertFalse(("Proxy-Authorization","FooBar") in
1047 https_handler.httpconn.req_headers)
1048 self.assertTrue(("User-Agent","Grail") in
1049 https_handler.httpconn.req_headers)
1050 self.assertIsNotNone(req._tunnel_host)
1051 self.assertEqual(req.get_host(), "proxy.example.com:3128")
1052 self.assertEqual(req.get_header("Proxy-authorization"),"FooBar")
Senthil Kumaran0ac1f832009-07-26 12:39:47 +00001053
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001054 def test_basic_auth(self, quote_char='"'):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001055 opener = OpenerDirector()
1056 password_manager = MockPasswordManager()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001057 auth_handler = urllib.request.HTTPBasicAuthHandler(password_manager)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001058 realm = "ACME Widget Store"
1059 http_handler = MockHTTPHandler(
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001060 401, 'WWW-Authenticate: Basic realm=%s%s%s\r\n\r\n' %
1061 (quote_char, realm, quote_char) )
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001062 opener.add_handler(auth_handler)
1063 opener.add_handler(http_handler)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001064 self._test_basic_auth(opener, auth_handler, "Authorization",
1065 realm, http_handler, password_manager,
1066 "http://acme.example.com/protected",
1067 "http://acme.example.com/protected",
1068 )
1069
Christian Heimes4fbc72b2008-03-22 00:47:35 +00001070 def test_basic_auth_with_single_quoted_realm(self):
1071 self.test_basic_auth(quote_char="'")
1072
Thomas Wouters477c8d52006-05-27 19:21:47 +00001073 def test_proxy_basic_auth(self):
1074 opener = OpenerDirector()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001075 ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
Thomas Wouters477c8d52006-05-27 19:21:47 +00001076 opener.add_handler(ph)
1077 password_manager = MockPasswordManager()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001078 auth_handler = urllib.request.ProxyBasicAuthHandler(password_manager)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001079 realm = "ACME Networks"
1080 http_handler = MockHTTPHandler(
1081 407, 'Proxy-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001082 opener.add_handler(auth_handler)
1083 opener.add_handler(http_handler)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001084 self._test_basic_auth(opener, auth_handler, "Proxy-authorization",
Thomas Wouters477c8d52006-05-27 19:21:47 +00001085 realm, http_handler, password_manager,
1086 "http://acme.example.com:3128/protected",
1087 "proxy.example.com:3128",
1088 )
1089
1090 def test_basic_and_digest_auth_handlers(self):
1091 # HTTPDigestAuthHandler threw an exception if it couldn't handle a 40*
1092 # response (http://python.org/sf/1479302), where it should instead
1093 # return None to allow another handler (especially
1094 # HTTPBasicAuthHandler) to handle the response.
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001095
1096 # Also (http://python.org/sf/14797027, RFC 2617 section 1.2), we must
1097 # try digest first (since it's the strongest auth scheme), so we record
1098 # order of calls here to check digest comes first:
1099 class RecordingOpenerDirector(OpenerDirector):
1100 def __init__(self):
1101 OpenerDirector.__init__(self)
1102 self.recorded = []
1103 def record(self, info):
1104 self.recorded.append(info)
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001105 class TestDigestAuthHandler(urllib.request.HTTPDigestAuthHandler):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001106 def http_error_401(self, *args, **kwds):
1107 self.parent.record("digest")
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001108 urllib.request.HTTPDigestAuthHandler.http_error_401(self,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001109 *args, **kwds)
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001110 class TestBasicAuthHandler(urllib.request.HTTPBasicAuthHandler):
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001111 def http_error_401(self, *args, **kwds):
1112 self.parent.record("basic")
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001113 urllib.request.HTTPBasicAuthHandler.http_error_401(self,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001114 *args, **kwds)
1115
1116 opener = RecordingOpenerDirector()
Thomas Wouters477c8d52006-05-27 19:21:47 +00001117 password_manager = MockPasswordManager()
1118 digest_handler = TestDigestAuthHandler(password_manager)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001119 basic_handler = TestBasicAuthHandler(password_manager)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001120 realm = "ACME Networks"
1121 http_handler = MockHTTPHandler(
1122 401, 'WWW-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001123 opener.add_handler(basic_handler)
1124 opener.add_handler(digest_handler)
1125 opener.add_handler(http_handler)
1126
1127 # check basic auth isn't blocked by digest handler failing
Thomas Wouters477c8d52006-05-27 19:21:47 +00001128 self._test_basic_auth(opener, basic_handler, "Authorization",
1129 realm, http_handler, password_manager,
1130 "http://acme.example.com/protected",
1131 "http://acme.example.com/protected",
1132 )
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001133 # check digest was tried before basic (twice, because
1134 # _test_basic_auth called .open() twice)
1135 self.assertEqual(opener.recorded, ["digest", "basic"]*2)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001136
1137 def _test_basic_auth(self, opener, auth_handler, auth_header,
1138 realm, http_handler, password_manager,
1139 request_url, protected_url):
Christian Heimes05e8be12008-02-23 18:30:17 +00001140 import base64
Thomas Wouters477c8d52006-05-27 19:21:47 +00001141 user, password = "wile", "coyote"
Thomas Wouters477c8d52006-05-27 19:21:47 +00001142
1143 # .add_password() fed through to password manager
1144 auth_handler.add_password(realm, request_url, user, password)
1145 self.assertEqual(realm, password_manager.realm)
1146 self.assertEqual(request_url, password_manager.url)
1147 self.assertEqual(user, password_manager.user)
1148 self.assertEqual(password, password_manager.password)
1149
1150 r = opener.open(request_url)
1151
1152 # should have asked the password manager for the username/password
1153 self.assertEqual(password_manager.target_realm, realm)
1154 self.assertEqual(password_manager.target_url, protected_url)
1155
1156 # expect one request without authorization, then one with
1157 self.assertEqual(len(http_handler.requests), 2)
1158 self.assertFalse(http_handler.requests[0].has_header(auth_header))
Guido van Rossum98b349f2007-08-27 21:47:52 +00001159 userpass = bytes('%s:%s' % (user, password), "ascii")
Guido van Rossum98297ee2007-11-06 21:34:58 +00001160 auth_hdr_value = ('Basic ' +
Georg Brandl706824f2009-06-04 09:42:55 +00001161 base64.encodebytes(userpass).strip().decode())
Thomas Wouters477c8d52006-05-27 19:21:47 +00001162 self.assertEqual(http_handler.requests[1].get_header(auth_header),
1163 auth_hdr_value)
Senthil Kumaranefcd8832010-02-24 16:56:20 +00001164 self.assertEqual(http_handler.requests[1].unredirected_hdrs[auth_header],
1165 auth_hdr_value)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001166 # if the password manager can't find a password, the handler won't
1167 # handle the HTTP auth error
1168 password_manager.user = password_manager.password = None
1169 http_handler.reset()
1170 r = opener.open(request_url)
1171 self.assertEqual(len(http_handler.requests), 1)
1172 self.assertFalse(http_handler.requests[0].has_header(auth_header))
1173
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001174class MiscTests(unittest.TestCase):
1175
1176 def test_build_opener(self):
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001177 class MyHTTPHandler(urllib.request.HTTPHandler): pass
1178 class FooHandler(urllib.request.BaseHandler):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001179 def foo_open(self): pass
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001180 class BarHandler(urllib.request.BaseHandler):
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001181 def bar_open(self): pass
1182
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001183 build_opener = urllib.request.build_opener
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001184
1185 o = build_opener(FooHandler, BarHandler)
1186 self.opener_has_handler(o, FooHandler)
1187 self.opener_has_handler(o, BarHandler)
1188
1189 # can take a mix of classes and instances
1190 o = build_opener(FooHandler, BarHandler())
1191 self.opener_has_handler(o, FooHandler)
1192 self.opener_has_handler(o, BarHandler)
1193
1194 # subclasses of default handlers override default handlers
1195 o = build_opener(MyHTTPHandler)
1196 self.opener_has_handler(o, MyHTTPHandler)
1197
1198 # a particular case of overriding: default handlers can be passed
1199 # in explicitly
1200 o = build_opener()
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001201 self.opener_has_handler(o, urllib.request.HTTPHandler)
1202 o = build_opener(urllib.request.HTTPHandler)
1203 self.opener_has_handler(o, urllib.request.HTTPHandler)
1204 o = build_opener(urllib.request.HTTPHandler())
1205 self.opener_has_handler(o, urllib.request.HTTPHandler)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001206
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001207 # Issue2670: multiple handlers sharing the same base class
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001208 class MyOtherHTTPHandler(urllib.request.HTTPHandler): pass
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001209 o = build_opener(MyHTTPHandler, MyOtherHTTPHandler)
1210 self.opener_has_handler(o, MyHTTPHandler)
1211 self.opener_has_handler(o, MyOtherHTTPHandler)
1212
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001213 def opener_has_handler(self, opener, handler_class):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +00001214 self.assertTrue(any(h.__class__ == handler_class
1215 for h in opener.handlers))
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001216
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001217class RequestTests(unittest.TestCase):
1218
1219 def setUp(self):
1220 self.get = Request("http://www.python.org/~jeremy/")
1221 self.post = Request("http://www.python.org/~jeremy/",
1222 "data",
1223 headers={"X-Test": "test"})
1224
1225 def test_method(self):
1226 self.assertEqual("POST", self.post.get_method())
1227 self.assertEqual("GET", self.get.get_method())
1228
1229 def test_add_data(self):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +00001230 self.assertFalse(self.get.has_data())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001231 self.assertEqual("GET", self.get.get_method())
1232 self.get.add_data("spam")
Georg Brandlab91fde2009-08-13 08:51:18 +00001233 self.assertTrue(self.get.has_data())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001234 self.assertEqual("POST", self.get.get_method())
1235
1236 def test_get_full_url(self):
1237 self.assertEqual("http://www.python.org/~jeremy/",
1238 self.get.get_full_url())
1239
1240 def test_selector(self):
1241 self.assertEqual("/~jeremy/", self.get.get_selector())
1242 req = Request("http://www.python.org/")
1243 self.assertEqual("/", req.get_selector())
1244
1245 def test_get_type(self):
1246 self.assertEqual("http", self.get.get_type())
1247
1248 def test_get_host(self):
1249 self.assertEqual("www.python.org", self.get.get_host())
1250
1251 def test_get_host_unquote(self):
1252 req = Request("http://www.%70ython.org/")
1253 self.assertEqual("www.python.org", req.get_host())
1254
1255 def test_proxy(self):
Florent Xiclunab4efb3d2010-08-14 18:24:40 +00001256 self.assertFalse(self.get.has_proxy())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001257 self.get.set_proxy("www.perl.org", "http")
Georg Brandlab91fde2009-08-13 08:51:18 +00001258 self.assertTrue(self.get.has_proxy())
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001259 self.assertEqual("www.python.org", self.get.get_origin_req_host())
1260 self.assertEqual("www.perl.org", self.get.get_host())
1261
Senthil Kumaran4c88db72010-08-08 11:30:58 +00001262 def test_wrapped_url(self):
1263 req = Request("<URL:http://www.python.org>")
1264 self.assertEqual("www.python.org", req.get_host())
1265
1266 def test_urlwith_fragment(self):
1267 req = Request("http://www.python.org/?qs=query#fragment=true")
1268 self.assertEqual("/?qs=query", req.get_selector())
1269 req = Request("http://www.python.org/#fun=true")
1270 self.assertEqual("/", req.get_selector())
1271
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001272
1273def test_main(verbose=None):
Thomas Wouters477c8d52006-05-27 19:21:47 +00001274 from test import test_urllib2
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 support.run_doctest(test_urllib2, verbose)
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001276 support.run_doctest(urllib.request, verbose)
Andrew M. Kuchlingbd3200f2004-06-29 13:15:46 +00001277 tests = (TrivialTests,
1278 OpenerDirectorTests,
1279 HandlerTests,
Benjamin Peterson6ebe78f2008-12-21 00:06:59 +00001280 MiscTests,
1281 RequestTests)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001282 support.run_unittest(*tests)
Jeremy Hyltonc1be59f2003-12-14 05:27:34 +00001283
1284if __name__ == "__main__":
1285 test_main(verbose=True)