# Source code for scrapy.downloadermiddlewares.redirect

    import logging
    from urllib.parse import urljoin, urlparse

    from w3lib.url import safe_url_string

    from scrapy.http import HtmlResponse
    from scrapy.utils.response import get_meta_refresh
    from scrapy.exceptions import IgnoreRequest, NotConfigured

    logger = logging.getLogger(__name__)

    class BaseRedirectMiddleware:

        enabled_setting = 'REDIRECT_ENABLED'

        def __init__(self, settings):
            if not settings.getbool(self.enabled_setting):
                raise NotConfigured

            self.max_redirect_times = settings.getint('REDIRECT_MAX_TIMES')
            self.priority_adjust = settings.getint('REDIRECT_PRIORITY_ADJUST')

        @classmethod
        def from_crawler(cls, crawler):
            return cls(crawler.settings)

        def _redirect(self, redirected, request, spider, reason):
            ttl = request.meta.setdefault('redirect_ttl', self.max_redirect_times)
            redirects = request.meta.get('redirect_times', 0) + 1

            if ttl and redirects <= self.max_redirect_times:
                redirected.meta['redirect_times'] = redirects
                redirected.meta['redirect_ttl'] = ttl - 1
                redirected.meta['redirect_urls'] = request.meta.get('redirect_urls', []) + [request.url]
                redirected.meta['redirect_reasons'] = request.meta.get('redirect_reasons', []) + [reason]
                redirected.dont_filter = request.dont_filter
                redirected.priority = request.priority + self.priority_adjust
                logger.debug("Redirecting (%(reason)s) to %(redirected)s from %(request)s",
                             {'reason': reason, 'redirected': redirected, 'request': request},
                             extra={'spider': spider})
                return redirected
            else:
                logger.debug("Discarding %(request)s: max redirections reached",
                             {'request': request}, extra={'spider': spider})
                raise IgnoreRequest("max redirections reached")

        def _redirect_request_using_get(self, request, redirect_url):
            redirected = request.replace(url=redirect_url, method='GET', body='')
            redirected.headers.pop('Content-Type', None)
            redirected.headers.pop('Content-Length', None)
            return redirected

    class RedirectMiddleware(BaseRedirectMiddleware):
        """
        Handle redirection of requests based on response status
        and meta-refresh html tag.
        """

        def process_response(self, request, response, spider):
            if (
                request.meta.get('dont_redirect', False)
                or response.status in getattr(spider, 'handle_httpstatus_list', [])
                or response.status in request.meta.get('handle_httpstatus_list', [])
                or request.meta.get('handle_httpstatus_all', False)
            ):
                return response

            allowed_status = (301, 302, 303, 307, 308)
            if 'Location' not in response.headers or response.status not in allowed_status:
                return response

            location = safe_url_string(response.headers['Location'])
            if response.headers['Location'].startswith(b'//'):
                request_scheme = urlparse(request.url).scheme
                location = request_scheme + '://' + location.lstrip('/')

            redirected_url = urljoin(request.url, location)

            if response.status in (301, 307, 308) or request.method == 'HEAD':
                redirected = request.replace(url=redirected_url)
                return self._redirect(redirected, request, spider, response.status)

            redirected = self._redirect_request_using_get(request, redirected_url)
            return self._redirect(redirected, request, spider, response.status)

    class MetaRefreshMiddleware(BaseRedirectMiddleware):

        enabled_setting = 'METAREFRESH_ENABLED'

        def __init__(self, settings):
            super().__init__(settings)
            self._ignore_tags = settings.getlist('METAREFRESH_IGNORE_TAGS')
            self._maxdelay = settings.getint('METAREFRESH_MAXDELAY')

        def process_response(self, request, response, spider):
            if (
                request.meta.get('dont_redirect', False)
                or request.method == 'HEAD'
                or not isinstance(response, HtmlResponse)
            ):
                return response

            interval, url = get_meta_refresh(response,
                                             ignore_tags=self._ignore_tags)
            if url and interval < self._maxdelay:
                redirected = self._redirect_request_using_get(request, url)
                return self._redirect(redirected, request, spider, 'meta refresh')

            return response