Почему Django HTTPResponseRedirect использует один и тот же HTTP-метод для PUT, но не POST?
У меня есть проект Django, где я использую представление для обработки различных HTTP-методов. POST
обрабатывал создание объекта, а затем перенаправлялся на тот же вид, что и GET
(или так я думал), используя Django redirect()
shortcut (HTTPResponseRedirect
), чтобы вернуть вновь созданный объект. Это отлично работает. Я пробовал то же самое с PUT
, но я попал в цикл перенаправления. Некоторое время царапая голову, я наткнулся на этот ответ SO, а затем я предположил, что, поскольку перенаправление не обрабатывает данные POST
, запрос превращается в GET
.
Я подтвердил это, просмотрев журналы, когда я делаю перенаправление с POST
:
[15/Dec/2014 00:47:43] "POST /client/151/ HTTP/1.1" 302 0
[15/Dec/2014 00:47:43] "GET /client/151/ HTTP/1.1" 200 395
Однако PUT
остается a PUT
и бросает меня в цикл перенаправления до тех пор, пока он не выйдет из строя.
[14/Dec/2014 23:07:36] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:37] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:37] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:38] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:38] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:39] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:39] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:40] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:40] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:41] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:41] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:42] "PUT /api/asset/6779/ HTTP/1.1" 302 0
Не следует ли использовать перенаправление GET
? Я понимаю, что происходит, но не знаю почему? Что дает?
ИЗМЕНИТЬ
# urls.py
url(r'^$', views.put_vs_post_redirect),
# views.py
from django.shortcuts import redirect
def put_vs_post_redirect(request, asset_id):
if request.method == 'GET':
return HTTPResponse('Get request')
elif request.method == 'POST':
return redirect('/')
elif request.method == 'PUT':
return redirect('/')
Ответы
Ответ 1
Как уже упоминалось в комментариях, это полностью зависит от клиента, и не все клиенты обрабатывают переадресации таким же образом. Вы можете найти достойное объяснение кодов переадресации и почему 301 должен удалить данные POST в Stack Overflow.
При работе с перенаправлением 301
(и часто 302
) большинство браузеров будут отбрасывать данные POST
и делать запрос GET
. Это происходит главным образом потому, что браузеры всегда это делали, а POST
запросы чаще всего поступают из веб-форм, поэтому имеет смысл, что перенаправление приводит к GET
, позволяя браузеру отображать другую страницу без вмешательства. Это не относится к вещам типа PUT
или PATCH
запросов, поскольку они в настоящее время не могут быть отправлены с помощью веб-форм и обычно играют по разным правилам.
Если вы хотите сохранить данные POST
при перенаправлении 302
, вы должны рассмотреть с помощью 307
redirect вместо. Запрос 307
должен поддерживать метод запроса и тело запроса в результате.
Если вы хотите сохранить данные POST
в перенаправлении 301
, в настоящее время черновик для кода состояния 308
, который будет работать как 307
, но будет постоянным.
Вы можете заставить перенаправление использовать запрос GET
с a 303
redirect. Он очень похож на 302
, но он гарантирует, что метод запроса всегда является запросом GET
. Он часто используется в API для асинхронных задач.
Ответ 2
Как мы можем использовать перманент 308 пермананет для POST apis в django rest framework
как перенаправить метод post в django-rest-framework