[TrackerIcon] Use httpdownloader page redirect handling

User reported infinite redirecting when attempting to fetch tracker
icon.

Fixed by allowing httpdownloader and RedirectAgent to handle page
redirects including catching infinite redirects

Trac: https://dev.deluge-torrent.org/ticket/3167
See-also: https://github.com/twisted/twisted/blob/5c24e9/src/twisted/web/client.py#L168
This commit is contained in:
Calum Lind 2022-04-30 17:40:29 +01:00
parent 61a83bbd20
commit 96a0825add
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
1 changed files with 13 additions and 44 deletions

View File

@ -13,7 +13,7 @@ from tempfile import mkstemp
from urllib.parse import urljoin, urlparse
from twisted.internet import defer, threads
from twisted.web.error import PageRedirect
from twisted.python.failure import Failure
from twisted.web.resource import ForbiddenResource, NoResource
from deluge.component import Component
@ -208,7 +208,6 @@ class TrackerIcons(Component):
d.addCallbacks(
self.on_download_page_complete,
self.on_download_page_fail,
errbackArgs=(host,),
)
d.addCallback(self.parse_html_page)
d.addCallbacks(
@ -242,7 +241,7 @@ class TrackerIcons(Component):
log.debug('Downloading %s %s', host, url)
tmp_fd, tmp_file = mkstemp(prefix='deluge_ticon.')
os.close(tmp_fd)
return download_file(url, tmp_file, force_filename=True, handle_redirects=False)
return download_file(url, tmp_file, force_filename=True)
def on_download_page_complete(self, page):
"""
@ -256,33 +255,18 @@ class TrackerIcons(Component):
log.debug('Finished downloading %s', page)
return page
def on_download_page_fail(self, f, host):
"""
Recovers from download error
def on_download_page_fail(self, failure: 'Failure') -> 'Failure':
"""Runs any download failure clean-up functions
:param f: the failure that occurred
:type f: Failure
:param host: the name of the host whose page failed to download
:type host: string
:returns: a Deferred if recovery was possible
else the original failure
:rtype: Deferred or Failure
"""
error_msg = f.getErrorMessage()
log.debug('Error downloading page: %s', error_msg)
d = f
if f.check(PageRedirect):
# Handle redirect errors
location = urljoin(self.host_to_url(host), error_msg.split(' to ')[1])
self.redirects[host] = url_to_host(location)
d = self.download_page(host, url=location)
d.addCallbacks(
self.on_download_page_complete,
self.on_download_page_fail,
errbackArgs=(host,),
)
Args:
failure: The failure that occurred.
return d
Returns:
The original failure.
"""
log.debug(f'Error downloading page: {failure.getErrorMessage()}')
return failure
@proxy(threads.deferToThread)
def parse_html_page(self, page):
@ -425,22 +409,7 @@ class TrackerIcons(Component):
error_msg = f.getErrorMessage()
log.debug('Error downloading icon from %s: %s', host, error_msg)
d = f
if f.check(PageRedirect):
# Handle redirect errors
location = urljoin(self.host_to_url(host), error_msg.split(' to ')[1])
d = self.download_icon(
[(location, extension_to_mimetype(location.rpartition('.')[2]))]
+ icons,
host,
)
if not icons:
d.addCallbacks(
self.on_download_icon_complete,
self.on_download_icon_fail,
callbackArgs=(host,),
errbackArgs=(host,),
)
elif f.check(NoResource, ForbiddenResource) and icons:
if f.check(NoResource, ForbiddenResource) and icons:
d = self.download_icon(icons, host)
elif f.check(NoIconsError):
# No icons, try favicon.ico as an act of desperation