Commit a0370225 authored by Martin Panter's avatar Martin Panter

Issue #12923: Reset FancyURLopener's redirect counter even on exception

Based on patches by Brian Brazil and Daniel Rocco.
parent 46f7785e
...@@ -39,10 +39,7 @@ def urlopen(url, data=None, proxies=None): ...@@ -39,10 +39,7 @@ def urlopen(url, data=None, proxies=None):
if proxies is not None: if proxies is not None:
opener = urllib.request.FancyURLopener(proxies=proxies) opener = urllib.request.FancyURLopener(proxies=proxies)
elif not _urlopener: elif not _urlopener:
with support.check_warnings( opener = FancyURLopener()
('FancyURLopener style of invoking requests is deprecated.',
DeprecationWarning)):
opener = urllib.request.FancyURLopener()
_urlopener = opener _urlopener = opener
else: else:
opener = _urlopener opener = _urlopener
...@@ -52,6 +49,13 @@ def urlopen(url, data=None, proxies=None): ...@@ -52,6 +49,13 @@ def urlopen(url, data=None, proxies=None):
return opener.open(url, data) return opener.open(url, data)
def FancyURLopener():
with support.check_warnings(
('FancyURLopener style of invoking requests is deprecated.',
DeprecationWarning)):
return urllib.request.FancyURLopener()
def fakehttp(fakedata): def fakehttp(fakedata):
class FakeSocket(io.BytesIO): class FakeSocket(io.BytesIO):
io_refs = 1 io_refs = 1
...@@ -291,11 +295,26 @@ Connection: close ...@@ -291,11 +295,26 @@ Connection: close
Content-Type: text/html; charset=iso-8859-1 Content-Type: text/html; charset=iso-8859-1
''') ''')
try: try:
self.assertRaises(urllib.error.HTTPError, urlopen, msg = "Redirection to url 'file:"
"http://python.org/") with self.assertRaisesRegex(urllib.error.HTTPError, msg):
urlopen("http://python.org/")
finally: finally:
self.unfakehttp() self.unfakehttp()
def test_redirect_limit_independent(self):
# Ticket #12923: make sure independent requests each use their
# own retry limit.
for i in range(FancyURLopener().maxtries):
self.fakehttp(b'''HTTP/1.1 302 Found
Location: file://guidocomputer.athome.com:/python/license
Connection: close
''')
try:
self.assertRaises(urllib.error.HTTPError, urlopen,
"http://something")
finally:
self.unfakehttp()
def test_empty_socket(self): def test_empty_socket(self):
# urlopen() raises OSError if the underlying socket does not send any # urlopen() raises OSError if the underlying socket does not send any
# data. (#1680230) # data. (#1680230)
......
...@@ -2050,18 +2050,20 @@ class FancyURLopener(URLopener): ...@@ -2050,18 +2050,20 @@ class FancyURLopener(URLopener):
def http_error_302(self, url, fp, errcode, errmsg, headers, data=None): def http_error_302(self, url, fp, errcode, errmsg, headers, data=None):
"""Error 302 -- relocated (temporarily).""" """Error 302 -- relocated (temporarily)."""
self.tries += 1 self.tries += 1
if self.maxtries and self.tries >= self.maxtries: try:
if hasattr(self, "http_error_500"): if self.maxtries and self.tries >= self.maxtries:
meth = self.http_error_500 if hasattr(self, "http_error_500"):
else: meth = self.http_error_500
meth = self.http_error_default else:
meth = self.http_error_default
return meth(url, fp, 500,
"Internal Server Error: Redirect Recursion",
headers)
result = self.redirect_internal(url, fp, errcode, errmsg,
headers, data)
return result
finally:
self.tries = 0 self.tries = 0
return meth(url, fp, 500,
"Internal Server Error: Redirect Recursion", headers)
result = self.redirect_internal(url, fp, errcode, errmsg, headers,
data)
self.tries = 0
return result
def redirect_internal(self, url, fp, errcode, errmsg, headers, data): def redirect_internal(self, url, fp, errcode, errmsg, headers, data):
if 'location' in headers: if 'location' in headers:
......
...@@ -1214,6 +1214,7 @@ Ben Roberts ...@@ -1214,6 +1214,7 @@ Ben Roberts
Mark Roberts Mark Roberts
Andy Robinson Andy Robinson
Jim Robinson Jim Robinson
Daniel Rocco
Mark Roddy Mark Roddy
Kevin Rodgers Kevin Rodgers
Sean Rodman Sean Rodman
......
...@@ -73,6 +73,9 @@ Core and Builtins ...@@ -73,6 +73,9 @@ Core and Builtins
Library Library
------- -------
- Issue #12923: Reset FancyURLopener's redirect counter even if there is an
exception. Based on patches by Brian Brazil and Daniel Rocco.
- Issue #25945: Fixed a crash when unpickle the functools.partial object with - Issue #25945: Fixed a crash when unpickle the functools.partial object with
wrong state. Fixed a leak in failed functools.partial constructor. wrong state. Fixed a leak in failed functools.partial constructor.
"args" and "keywords" attributes of functools.partial have now always types "args" and "keywords" attributes of functools.partial have now always types
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment