mirror of
https://github.com/kennethreitz/requests.git
synced 2026-06-05 22:50:18 +00:00
Merge pull request #3060 from benweatherman/master
Consolidate logic for changing method during redirects
This commit is contained in:
+23
-17
@@ -116,7 +116,6 @@ class SessionRedirectMixin(object):
|
||||
resp.close()
|
||||
|
||||
url = resp.headers['location']
|
||||
method = req.method
|
||||
|
||||
# Handle redirection without scheme (see: RFC 1808 Section 4)
|
||||
if url.startswith('//'):
|
||||
@@ -140,22 +139,7 @@ class SessionRedirectMixin(object):
|
||||
if resp.is_permanent_redirect and req.url != prepared_request.url:
|
||||
self.redirect_cache[req.url] = prepared_request.url
|
||||
|
||||
# http://tools.ietf.org/html/rfc7231#section-6.4.4
|
||||
if (resp.status_code == codes.see_other and
|
||||
method != 'HEAD'):
|
||||
method = 'GET'
|
||||
|
||||
# Do what the browsers do, despite standards...
|
||||
# First, turn 302s into GETs.
|
||||
if resp.status_code == codes.found and method != 'HEAD':
|
||||
method = 'GET'
|
||||
|
||||
# Second, if a POST is responded to with a 301, turn it into a GET.
|
||||
# This bizarre behaviour is explained in Issue 1704.
|
||||
if resp.status_code == codes.moved and method == 'POST':
|
||||
method = 'GET'
|
||||
|
||||
prepared_request.method = method
|
||||
self.rebuild_method(prepared_request, resp)
|
||||
|
||||
# https://github.com/kennethreitz/requests/issues/1084
|
||||
if resp.status_code not in (codes.temporary_redirect, codes.permanent_redirect):
|
||||
@@ -262,6 +246,28 @@ class SessionRedirectMixin(object):
|
||||
|
||||
return new_proxies
|
||||
|
||||
def rebuild_method(self, prepared_request, response):
|
||||
"""When being redirected we may want to change the method of the request
|
||||
based on certain specs or browser behavior.
|
||||
"""
|
||||
method = prepared_request.method
|
||||
|
||||
# http://tools.ietf.org/html/rfc7231#section-6.4.4
|
||||
if response.status_code == codes.see_other and method != 'HEAD':
|
||||
method = 'GET'
|
||||
|
||||
# Do what the browsers do, despite standards...
|
||||
# First, turn 302s into GETs.
|
||||
if response.status_code == codes.found and method != 'HEAD':
|
||||
method = 'GET'
|
||||
|
||||
# Second, if a POST is responded to with a 301, turn it into a GET.
|
||||
# This bizarre behaviour is explained in Issue 1704.
|
||||
if response.status_code == codes.moved and method == 'POST':
|
||||
method = 'GET'
|
||||
|
||||
prepared_request.method = method
|
||||
|
||||
|
||||
class Session(SessionRedirectMixin):
|
||||
"""A Requests session.
|
||||
|
||||
@@ -162,6 +162,49 @@ class TestRequests:
|
||||
else:
|
||||
pytest.fail('Expected custom max number of redirects to be respected but was not')
|
||||
|
||||
def test_http_301_changes_post_to_get(self, httpbin):
|
||||
r = requests.post(httpbin('status', '301'))
|
||||
assert r.status_code == 200
|
||||
assert r.request.method == 'GET'
|
||||
assert r.history[0].status_code == 301
|
||||
assert r.history[0].is_redirect
|
||||
|
||||
def test_http_301_doesnt_change_head_to_get(self, httpbin):
|
||||
r = requests.head(httpbin('status', '301'), allow_redirects=True)
|
||||
print(r.content)
|
||||
assert r.status_code == 200
|
||||
assert r.request.method == 'HEAD'
|
||||
assert r.history[0].status_code == 301
|
||||
assert r.history[0].is_redirect
|
||||
|
||||
def test_http_302_changes_post_to_get(self, httpbin):
|
||||
r = requests.post(httpbin('status', '302'))
|
||||
assert r.status_code == 200
|
||||
assert r.request.method == 'GET'
|
||||
assert r.history[0].status_code == 302
|
||||
assert r.history[0].is_redirect
|
||||
|
||||
def test_http_302_doesnt_change_head_to_get(self, httpbin):
|
||||
r = requests.head(httpbin('status', '302'), allow_redirects=True)
|
||||
assert r.status_code == 200
|
||||
assert r.request.method == 'HEAD'
|
||||
assert r.history[0].status_code == 302
|
||||
assert r.history[0].is_redirect
|
||||
|
||||
def test_http_303_changes_post_to_get(self, httpbin):
|
||||
r = requests.post(httpbin('status', '303'))
|
||||
assert r.status_code == 200
|
||||
assert r.request.method == 'GET'
|
||||
assert r.history[0].status_code == 303
|
||||
assert r.history[0].is_redirect
|
||||
|
||||
def test_http_303_doesnt_change_head_to_get(self, httpbin):
|
||||
r = requests.head(httpbin('status', '303'), allow_redirects=True)
|
||||
assert r.status_code == 200
|
||||
assert r.request.method == 'HEAD'
|
||||
assert r.history[0].status_code == 303
|
||||
assert r.history[0].is_redirect
|
||||
|
||||
# def test_HTTP_302_ALLOW_REDIRECT_POST(self):
|
||||
# r = requests.post(httpbin('status', '302'), data={'some': 'data'})
|
||||
# self.assertEqual(r.status_code, 200)
|
||||
|
||||
Reference in New Issue
Block a user