prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Redirect 308 missing
  I did a check on the RedirectMiddleware and noticed that code 308 is missing. Is there a reason for that?
  Some websites don't update their sitemap and have a long list of 308 from http to https.
  
  (side note: is there a way to add "s" before a link is scraped?)
  
  </issue>
  <code>
  [start of scrapy/downloadermiddlewares/redirect.py]
  1 import logging
  2 from six.moves.urllib.parse import urljoin
  3 
  4 from w3lib.url import safe_url_string
  5 
  6 from scrapy.http import HtmlResponse
  7 from scrapy.utils.response import get_meta_refresh
  8 from scrapy.exceptions import IgnoreRequest, NotConfigured
  9 
  10 logger = logging.getLogger(__name__)
  11 
  12 
  13 class BaseRedirectMiddleware(object):
  14 
  15     enabled_setting = 'REDIRECT_ENABLED'
  16 
  17     def __init__(self, settings):
  18         if not settings.getbool(self.enabled_setting):
  19             raise NotConfigured
  20 
  21         self.max_redirect_times = settings.getint('REDIRECT_MAX_TIMES')
  22         self.priority_adjust = settings.getint('REDIRECT_PRIORITY_ADJUST')
  23 
  24     @classmethod
  25     def from_crawler(cls, crawler):
  26         return cls(crawler.settings)
  27 
  28     def _redirect(self, redirected, request, spider, reason):
  29         ttl = request.meta.setdefault('redirect_ttl', self.max_redirect_times)
  30         redirects = request.meta.get('redirect_times', 0) + 1
  31 
  32         if ttl and redirects <= self.max_redirect_times:
  33             redirected.meta['redirect_times'] = redirects
  34             redirected.meta['redirect_ttl'] = ttl - 1
  35             redirected.meta['redirect_urls'] = request.meta.get('redirect_urls', []) + \
  36                 [request.url]
  37             redirected.dont_filter = request.dont_filter
  38             redirected.priority = request.priority + self.priority_adjust
  39             logger.debug("Redirecting (%(reason)s) to %(redirected)s from %(request)s",
  40                          {'reason': reason, 'redirected': redirected, 'request': request},
  41                          extra={'spider': spider})
  42             return redirected
  43         else:
  44             logger.debug("Discarding %(request)s: max redirections reached",
  45                          {'request': request}, extra={'spider': spider})
  46             raise IgnoreRequest("max redirections reached")
  47 
  48     def _redirect_request_using_get(self, request, redirect_url):
  49         redirected = request.replace(url=redirect_url, method='GET', body='')
  50         redirected.headers.pop('Content-Type', None)
  51         redirected.headers.pop('Content-Length', None)
  52         return redirected
  53 
  54 
  55 class RedirectMiddleware(BaseRedirectMiddleware):
  56     """
  57     Handle redirection of requests based on response status
  58     and meta-refresh html tag.
  59     """
  60     def process_response(self, request, response, spider):
  61         if (request.meta.get('dont_redirect', False) or
  62                 response.status in getattr(spider, 'handle_httpstatus_list', []) or
  63                 response.status in request.meta.get('handle_httpstatus_list', []) or
  64                 request.meta.get('handle_httpstatus_all', False)):
  65             return response
  66 
  67         allowed_status = (301, 302, 303, 307)
  68         if 'Location' not in response.headers or response.status not in allowed_status:
  69             return response
  70 
  71         location = safe_url_string(response.headers['location'])
  72 
  73         redirected_url = urljoin(request.url, location)
  74 
  75         if response.status in (301, 307) or request.method == 'HEAD':
  76             redirected = request.replace(url=redirected_url)
  77             return self._redirect(redirected, request, spider, response.status)
  78 
  79         redirected = self._redirect_request_using_get(request, redirected_url)
  80         return self._redirect(redirected, request, spider, response.status)
  81 
  82 
  83 class MetaRefreshMiddleware(BaseRedirectMiddleware):
  84 
  85     enabled_setting = 'METAREFRESH_ENABLED'
  86 
  87     def __init__(self, settings):
  88         super(MetaRefreshMiddleware, self).__init__(settings)
  89         self._maxdelay = settings.getint('REDIRECT_MAX_METAREFRESH_DELAY',
  90                                          settings.getint('METAREFRESH_MAXDELAY'))
  91 
  92     def process_response(self, request, response, spider):
  93         if request.meta.get('dont_redirect', False) or request.method == 'HEAD' or \
  94                 not isinstance(response, HtmlResponse):
  95             return response
  96 
  97         interval, url = get_meta_refresh(response)
  98         if url and interval < self._maxdelay:
  99             redirected = self._redirect_request_using_get(request, url)
  100             return self._redirect(redirected, request, spider, 'meta refresh')
  101 
  102         return response
  103
  [end of scrapy/downloadermiddlewares/redirect.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/scrapy/downloadermiddlewares/redirect.py b/scrapy/downloadermiddlewares/redirect.py
  --- a/scrapy/downloadermiddlewares/redirect.py
  +++ b/scrapy/downloadermiddlewares/redirect.py
  @@ -64,7 +64,7 @@
                   request.meta.get('handle_httpstatus_all', False)):
               return response
   
  -        allowed_status = (301, 302, 303, 307)
  +        allowed_status = (301, 302, 303, 307, 308)
           if 'Location' not in response.headers or response.status not in allowed_status:
               return response
   
  @@ -72,7 +72,7 @@
   
           redirected_url = urljoin(request.url, location)
   
  -        if response.status in (301, 307) or request.method == 'HEAD':
  +        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)
  
verification_info: {"golden_diff": "diff --git a/scrapy/downloadermiddlewares/redirect.py b/scrapy/downloadermiddlewares/redirect.py\n--- a/scrapy/downloadermiddlewares/redirect.py\n+++ b/scrapy/downloadermiddlewares/redirect.py\n@@ -64,7 +64,7 @@\n                 request.meta.get('handle_httpstatus_all', False)):\n             return response\n \n-        allowed_status = (301, 302, 303, 307)\n+        allowed_status = (301, 302, 303, 307, 308)\n         if 'Location' not in response.headers or response.status not in allowed_status:\n             return response\n \n@@ -72,7 +72,7 @@\n \n         redirected_url = urljoin(request.url, location)\n \n-        if response.status in (301, 307) or request.method == 'HEAD':\n+        if response.status in (301, 307, 308) or request.method == 'HEAD':\n             redirected = request.replace(url=redirected_url)\n             return self._redirect(redirected, request, spider, response.status)\n", "issue": "Redirect 308 missing\nI did a check on the RedirectMiddleware and noticed that code 308 is missing. Is there a reason for that?\r\nSome websites don't update their sitemap and have a long list of 308 from http to https.\r\n\r\n(side note: is there a way to add \"s\" before a link is scraped?)\n", "before_files": [{"content": "import logging\nfrom six.moves.urllib.parse import urljoin\n\nfrom w3lib.url import safe_url_string\n\nfrom scrapy.http import HtmlResponse\nfrom scrapy.utils.response import get_meta_refresh\nfrom scrapy.exceptions import IgnoreRequest, NotConfigured\n\nlogger = logging.getLogger(__name__)\n\n\nclass BaseRedirectMiddleware(object):\n\n    enabled_setting = 'REDIRECT_ENABLED'\n\n    def __init__(self, settings):\n        if not settings.getbool(self.enabled_setting):\n            raise NotConfigured\n\n        self.max_redirect_times = settings.getint('REDIRECT_MAX_TIMES')\n        self.priority_adjust = settings.getint('REDIRECT_PRIORITY_ADJUST')\n\n    @classmethod\n    def from_crawler(cls, crawler):\n        return cls(crawler.settings)\n\n    def _redirect(self, redirected, request, spider, reason):\n        ttl = request.meta.setdefault('redirect_ttl', self.max_redirect_times)\n        redirects = request.meta.get('redirect_times', 0) + 1\n\n        if ttl and redirects <= self.max_redirect_times:\n            redirected.meta['redirect_times'] = redirects\n            redirected.meta['redirect_ttl'] = ttl - 1\n            redirected.meta['redirect_urls'] = request.meta.get('redirect_urls', []) + \\\n                [request.url]\n            redirected.dont_filter = request.dont_filter\n            redirected.priority = request.priority + self.priority_adjust\n            logger.debug(\"Redirecting (%(reason)s) to %(redirected)s from %(request)s\",\n                         {'reason': reason, 'redirected': redirected, 'request': request},\n                         extra={'spider': spider})\n            return redirected\n        else:\n            logger.debug(\"Discarding %(request)s: max redirections reached\",\n                         {'request': request}, extra={'spider': spider})\n            raise IgnoreRequest(\"max redirections reached\")\n\n    def _redirect_request_using_get(self, request, redirect_url):\n        redirected = request.replace(url=redirect_url, method='GET', body='')\n        redirected.headers.pop('Content-Type', None)\n        redirected.headers.pop('Content-Length', None)\n        return redirected\n\n\nclass RedirectMiddleware(BaseRedirectMiddleware):\n    \"\"\"\n    Handle redirection of requests based on response status\n    and meta-refresh html tag.\n    \"\"\"\n    def process_response(self, request, response, spider):\n        if (request.meta.get('dont_redirect', False) or\n                response.status in getattr(spider, 'handle_httpstatus_list', []) or\n                response.status in request.meta.get('handle_httpstatus_list', []) or\n                request.meta.get('handle_httpstatus_all', False)):\n            return response\n\n        allowed_status = (301, 302, 303, 307)\n        if 'Location' not in response.headers or response.status not in allowed_status:\n            return response\n\n        location = safe_url_string(response.headers['location'])\n\n        redirected_url = urljoin(request.url, location)\n\n        if response.status in (301, 307) or request.method == 'HEAD':\n            redirected = request.replace(url=redirected_url)\n            return self._redirect(redirected, request, spider, response.status)\n\n        redirected = self._redirect_request_using_get(request, redirected_url)\n        return self._redirect(redirected, request, spider, response.status)\n\n\nclass MetaRefreshMiddleware(BaseRedirectMiddleware):\n\n    enabled_setting = 'METAREFRESH_ENABLED'\n\n    def __init__(self, settings):\n        super(MetaRefreshMiddleware, self).__init__(settings)\n        self._maxdelay = settings.getint('REDIRECT_MAX_METAREFRESH_DELAY',\n                                         settings.getint('METAREFRESH_MAXDELAY'))\n\n    def process_response(self, request, response, spider):\n        if request.meta.get('dont_redirect', False) or request.method == 'HEAD' or \\\n                not isinstance(response, HtmlResponse):\n            return response\n\n        interval, url = get_meta_refresh(response)\n        if url and interval < self._maxdelay:\n            redirected = self._redirect_request_using_get(request, url)\n            return self._redirect(redirected, request, spider, 'meta refresh')\n\n        return response\n", "path": "scrapy/downloadermiddlewares/redirect.py"}]}