为什么POST重定向到GET和PUT重定向到PUT?

use*_*521 8 http node.js express

我使用快递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
Run Code Online (Sandbox Code Playgroud)

POST重定向到GET,但PUT重定向到PUT.是否可以使PUT重定向到GET(与POST相同)?

xav*_*ert 12

在深入了解详细信息之前,以下是解决问题的方法之一:

app.put('/test', function(req, res, next) {
    res.redirect(303, '/test') // Notice the 303 parameter
})
Run Code Online (Sandbox Code Playgroud)

默认情况下,Express使用HTTP代码302进行重定向.根据HTTP规范,这可以防止POST/PUT请求被重定向为POST/PUT请求,并解释您在代码中观察到的内容:

如果收到302状态代码以响应GET或HEAD以外的请求,则用户代理不得自动重定向请求,除非用户可以确认,因为这可能会改变发出请求的条件.

另一方面,如果您使用303重定向,则允许将POST/PUT请求重定向为POST/PUT请求,如此SO答案中所述:

303:重定向未定义的原因.通常,'行动已经完成,继续在其他地方.对此资源发出后续请求的客户端不应使用新URI.客户端应遵循POST/PUT/DELETE请求的重定向.

  • @ user606521最新的HTTP 1.1规范特别允许302重定向将POST更改为GET.(请参阅我的答案中RFC的相关引用.)规范不允许超出特定POST-to-GET更改的任何其他转换,因此PUT仍然是PUT.这是出于历史原因; 即,浏览器实现了原始规范错误,并且规范已更改为允许此错误. (2认同)

aps*_*ers 10

首先,让我们明白了什么res.redirect:

res.redirect([status,] path)

使用指定的HTTP状态代码状态重定向到从指定路径派生的URL.如果未指定status,则状态代码默认为"302"Found".

如果我们看一下302响应HTTP 1.1规范,我们会看到

注意:由于历史原因,用户代理可以将请求方法从POST更改为GET以用于后续请求.如果不希望出现此行为,则可以使用307(临时重定向)状态代码.

307请求将在所有情况下保留HTTP动词,但这不是您想要的.您希望动词更改为GET.在这种情况下,你想要一个303:

303见其他

303(请参阅其他)状态代码表示服务器正在将用户代理重定向到其他资源,如Location头字段中的URI所示,该URI旨在提供对原始请求的间接响应.用户代理可以执行针对该URI的检索请求(如果使用HTTP则为GET或HEAD请求),其也可以被重定向,并将最终结果作为原始请求的答案呈现.

303响应将提示客户端(假设它理解HTTP 1.1)以对指定资源执行GET请求.因此,只需在重定向中提供303状态代码:

res.redirect(303, '/test')
Run Code Online (Sandbox Code Playgroud)