From a03702252f591e477db0576bea589d21afdfa601 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Thu, 4 Feb 2016 06:01:35 +0000 Subject: Issue #12923: Reset FancyURLopener's redirect counter even on exception Based on patches by Brian Brazil and Daniel Rocco. --- Lib/test/test_urllib.py | 31 +++++++++++++++++++++++++------ Lib/urllib/request.py | 24 +++++++++++++----------- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 57eeeaa..e197a3f 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -39,10 +39,7 @@ def urlopen(url, data=None, proxies=None): if proxies is not None: opener = urllib.request.FancyURLopener(proxies=proxies) elif not _urlopener: - with support.check_warnings( - ('FancyURLopener style of invoking requests is deprecated.', - DeprecationWarning)): - opener = urllib.request.FancyURLopener() + opener = FancyURLopener() _urlopener = opener else: opener = _urlopener @@ -52,6 +49,13 @@ def urlopen(url, data=None, proxies=None): 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): class FakeSocket(io.BytesIO): io_refs = 1 @@ -291,11 +295,26 @@ Connection: close Content-Type: text/html; charset=iso-8859-1 ''') try: - self.assertRaises(urllib.error.HTTPError, urlopen, - "http://python.org/") + msg = "Redirection to url 'file:" + with self.assertRaisesRegex(urllib.error.HTTPError, msg): + urlopen("http://python.org/") finally: 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): # urlopen() raises OSError if the underlying socket does not send any # data. (#1680230) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index a7fd017..4c16518 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -2050,18 +2050,20 @@ class FancyURLopener(URLopener): def http_error_302(self, url, fp, errcode, errmsg, headers, data=None): """Error 302 -- relocated (temporarily).""" self.tries += 1 - if self.maxtries and self.tries >= self.maxtries: - if hasattr(self, "http_error_500"): - meth = self.http_error_500 - else: - meth = self.http_error_default + try: + if self.maxtries and self.tries >= self.maxtries: + if hasattr(self, "http_error_500"): + meth = self.http_error_500 + 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 - 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): if 'location' in headers: diff --git a/Misc/ACKS b/Misc/ACKS index b07244a..9fa22e1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1214,6 +1214,7 @@ Ben Roberts Mark Roberts Andy Robinson Jim Robinson +Daniel Rocco Mark Roddy Kevin Rodgers Sean Rodman diff --git a/Misc/NEWS b/Misc/NEWS index 691c533..5aa57b9 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -73,6 +73,9 @@ Core and Builtins 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 wrong state. Fixed a leak in failed functools.partial constructor. "args" and "keywords" attributes of functools.partial have now always types -- cgit v0.12