diff --git a/scrapy/downloadermiddlewares/redirect.py b/scrapy/downloadermiddlewares/redirect.py index a26715e12..36bd9a849 100644 --- a/scrapy/downloadermiddlewares/redirect.py +++ b/scrapy/downloadermiddlewares/redirect.py @@ -38,18 +38,19 @@ def _build_redirect_request(source_request, *, url, **kwargs): or default_ports.get(parsed_redirect_request.scheme), ) - if redirect_scheme != "https" or source_host != redirect_host: - if has_cookie_header: - del redirect_request.headers["Cookie"] + if has_cookie_header and ( + (source_scheme != redirect_scheme and redirect_scheme != "https") + or source_host != redirect_host + ): + del redirect_request.headers["Cookie"] - if ( + # https://fetch.spec.whatwg.org/#ref-for-cors-non-wildcard-request-header-name + if has_authorization_header and ( source_scheme != redirect_scheme or source_host != redirect_host or source_port != redirect_port ): - # https://fetch.spec.whatwg.org/#ref-for-cors-non-wildcard-request-header-name - if has_authorization_header: - del redirect_request.headers["Authorization"] + del redirect_request.headers["Authorization"] return redirect_request diff --git a/tests/test_downloadermiddleware_redirect.py b/tests/test_downloadermiddleware_redirect.py index c14f87d91..3b0b910ee 100644 --- a/tests/test_downloadermiddleware_redirect.py +++ b/tests/test_downloadermiddleware_redirect.py @@ -270,6 +270,23 @@ class RedirectMiddlewareTest(unittest.TestCase): self.assertIsInstance(internal_redirect_request, Request) self.assertEqual(original_request.headers, internal_redirect_request.headers) + # Redirects to the same origin (same scheme, same domain, same port) + # keep all headers also when the scheme is http. + http_request = Request( + "http://example.com", + headers={**safe_headers, **cookie_header, **authorization_header}, + ) + http_response = Response( + "http://example.com", + headers={"Location": "http://example.com/a"}, + status=301, + ) + http_redirect_request = self.mw.process_response( + http_request, http_response, self.spider + ) + self.assertIsInstance(http_redirect_request, Request) + self.assertEqual(http_request.headers, http_redirect_request.headers) + # For default ports, whether the port is explicit or implicit does not # affect the outcome, it is still the same origin. to_explicit_port_response = Response( @@ -334,10 +351,6 @@ class RedirectMiddlewareTest(unittest.TestCase): # A scheme upgrade (http → https) drops the Authorization header # because the origin changes, but keeps the Cookie header because the # domain remains the same. - http_request = Request( - "http://example.com", - headers={**safe_headers, **cookie_header, **authorization_header}, - ) upgrade_response = Response( "http://example.com", headers={"Location": "https://example.com/a"},