Почему POST перенаправляет на GET, а PUT перенаправляет на PUT?
Я использую экспресс 4.13.3
(последний) и следующий код:
var express = require('express')
var app = express()
app.get('/test', function (req, res, next) {
res.send('hello!')
})
app.post('/test', function (req, res, next) {
res.redirect('/test')
})
app.put('/test', function (req, res, next) {
res.redirect('/test')
})
app.listen(5001)
// GET /test -> 'hello!'
// POST /test -> 'hello!'
// PUT /test -> ERR_TOO_MANY_REDIRECTS
POST перенаправляет на GET, но PUT перенаправляет на PUT. Можно ли сделать PUT перенаправления на GET (так же, как POST)?
3 ответа
Перед тем, как погрузиться в детали, ниже приведен один из способов решения проблемы:
app.put('/test', function(req, res, next) {
res.redirect(303, '/test') // Notice the 303 parameter
})
По умолчанию Express использует HTTP-код 302 для перенаправления. Согласно спецификации HTTP, это предотвращает перенаправление запросов POST/PUT как запросов POST/PUT и объясняет, что вы наблюдали в своем коде:
Если код состояния 302 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, при которых был выполнен запрос.
С другой стороны, если вы используете перенаправление 303, запрос POST/PUT может быть перенаправлен как запрос POST/PUT, как объяснено в этом замечательном ответе SO:
303: Перенаправление по неопределенной причине. Как правило, "Операция завершена, продолжить в другом месте". Клиенты, делающие последующие запросы на этот ресурс, не должны использовать новый URI. Клиенты должны следовать перенаправлению для запросов POST/PUT/DELETE.
Для начала давайте разберемся, что res.redirect
делает:
res.redirect ([статус,] путь)
Перенаправляет на URL-адрес, полученный по указанному пути, с указанным статусом кода состояния HTTP. Если вы не укажете статус, код состояния по умолчанию будет "302" Найдено ".
Если мы посмотрим на спецификации HTTP 1.1 для ответа 302, мы увидим
Примечание. По историческим причинам пользовательский агент МОЖЕТ изменить метод запроса с POST на GET для последующего запроса. Если это поведение нежелательно, вместо него можно использовать код состояния 307 (временное перенаправление).
Запрос 307 сохранит глагол HTTP во всех случаях, но вы этого не хотите. Вы хотите, чтобы глагол изменился на GET. В этом случае вы хотите 303:
303 См. Другое
Код состояния 303 (см. "Другое") указывает, что сервер перенаправляет пользовательский агент на другой ресурс, как указано URI в поле заголовка Location, который предназначен для предоставления косвенного ответа на исходный запрос. Пользовательский агент может выполнить запрос поиска, направленный на этот URI (запрос GET или HEAD, если используется HTTP), который также может быть перенаправлен, и представить конечный результат в качестве ответа на исходный запрос.
Ответ 303 предложит клиенту (при условии, что он понимает HTTP 1.1) выполнить запрос GET для указанного ресурса. Итак, просто укажите код состояния 303 в ваших перенаправлениях:
res.redirect(303, '/test')
Способ размещения верен, вы перенаправляете запрос в другое место, но метод http такой же. И именно поэтому он пытается получить доступ put
снова. (Вы не меняете метод http.)
Зачем
post
перенаправляет наget
Вот ответ.