mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
Issue #12923: Reset FancyURLopener's redirect counter even on exception
Based on patches by Brian Brazil and Daniel Rocco.
This commit is contained in:
parent
46f7785e28
commit
a03702252f
4 changed files with 42 additions and 17 deletions
|
|
@ -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):
|
||||||
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
|
||||||
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):
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue