为什么POSTredirect到GET和PUTredirect到PUT?

我使用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 

POSTredirect到GET,但PUTredirect到PUT。 是否有可能使PUTredirect到GET(与POST相同)?

在深入细节之前,下面是如何解决问题的一种方法:

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

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

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

另一方面,如果你使用303redirect,POST / PUT请求被允许被redirect为一个POST / PUT请求,正如在这个伟大的答案中所解释的那样:

303:redirect为未定义的原因。 通常,“操作已经完成,在其他地方继续”。 随后请求这个资源的客户端不应该使用新的URI。 客户端应该遵循POST / PUT / DELETE请求的redirect。

首先,让我们了解res.redirect作用 :

res.redirect([status,]path)

使用指定的HTTP状态码状态redirect到从指定path派生的URL。 如果您不指定状态,则状态代码默认为“302”find“。

如果我们查看一个302响应的HTTP 1.1规范 ,我们可以看到

注意:由于历史原因,用户代理可能会将请求方法从POST更改为GET,以供后续请求使用。 如果这种行为是不希望的,则可以使用307(临时redirect)状态码。

在所有情况下,307请求都会保留HTTP动词,但那不是你想要的。 你想动词改变为GET。 在这种情况下,你想要一个303 :

303见其他

303(请参见其他)状态码指示服务器正在将用户代理redirect到不同的资源,如位置标题字段中的URI所示,旨在提供对原始请求的间接响应。 用户代理可以执行针对该URI的检索请求( 如果使用HTTP则为GET或HEAD请求 ),并且可能会被redirect,并将最终结果作为原始请求的答案。

303响应将提示客户端(只要它理解HTTP 1.1)在指定资源上执行GET请求。 所以,只需在您的redirect中提供一个303状态码:

 res.redirect(303, '/test') 

放的方式是正确的,你正在redirect请求到另一个位置,但http方法是一样的。 这就是为什么它试图再次访问。 (你没有改变http方法。)

为什么postredirectget

这是答案 。