diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py index 3279c1c3..505e6d70 100644 --- a/python2/httplib2/__init__.py +++ b/python2/httplib2/__init__.py @@ -294,6 +294,9 @@ class NotRunningAppEngineEnvironment(HttpLib2Error): # https://tools.ietf.org/html/rfc7231#section-8.1.3 SAFE_METHODS = ("GET", "HEAD") # TODO add "OPTIONS", "TRACE" +# To change, assign to `Http().redirect_codes` +REDIRECT_CODES = frozenset((300, 301, 302, 303, 307, 308)) + def _get_end2end_headers(response): hopbyhop = list(HOP_BY_HOP) @@ -1664,6 +1667,8 @@ def __init__( # If set to False then no redirects are followed, even safe ones. self.follow_redirects = True + self.redirect_codes = REDIRECT_CODES + # Which HTTP methods do we apply optimistic concurrency to, i.e. # which methods get an "if-match:" etag header added to them. self.optimistic_concurrency_methods = ["PUT", "PATCH"] @@ -1866,7 +1871,7 @@ def _request( or method in self.safe_methods or response.status in (303, 308) ): - if self.follow_redirects and response.status in (300, 301, 302, 303, 307, 308): + if self.follow_redirects and response.status in self.redirect_codes: # Pick out the location header and basically start from the beginning # remembering first to strip the ETag header and decrement our 'depth' if redirections: diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py index 9884f15b..a16f8006 100644 --- a/python3/httplib2/__init__.py +++ b/python3/httplib2/__init__.py @@ -164,6 +164,9 @@ class ProxiesUnavailableError(HttpLib2Error): # https://tools.ietf.org/html/rfc7231#section-8.1.3 SAFE_METHODS = ("GET", "HEAD", "OPTIONS", "TRACE") +# To change, assign to `Http().redirect_codes` +REDIRECT_CODES = frozenset((300, 301, 302, 303, 307, 308)) + from httplib2 import certs CA_CERTS = certs.where() @@ -1471,6 +1474,8 @@ def __init__( # If set to False then no redirects are followed, even safe ones. self.follow_redirects = True + self.redirect_codes = REDIRECT_CODES + # Which HTTP methods do we apply optimistic concurrency to, i.e. # which methods get an "if-match:" etag header added to them. self.optimistic_concurrency_methods = ["PUT", "PATCH"] @@ -1672,7 +1677,7 @@ def _request( or method in self.safe_methods or response.status in (303, 308) ): - if self.follow_redirects and response.status in (300, 301, 302, 303, 307, 308): + if self.follow_redirects and response.status in self.redirect_codes: # Pick out the location header and basically start from the beginning # remembering first to strip the ETag header and decrement our 'depth' if redirections: diff --git a/tests/test_http.py b/tests/test_http.py index 641a647c..df990167 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -694,3 +694,12 @@ def test_get_duplicate_headers(): assert response.status == 200 assert content == b"content" assert response["link"], "link1, link2" + + +def test_custom_redirect_codes(): + http = httplib2.Http() + http.redirect_codes = set([300]) + with tests.server_const_http(status=301, request_count=1) as uri: + response, content = http.request(uri, "GET") + assert response.status == 301 + assert response.previous is None