javascript – 使用相同的URL快速将POST重定向到PUT

在我的快递应用程序中,我有两条路线如下:

router.post('/:date', (req, res) => {

    // if date exists, redirect to PUT
    // else add to database

})

router.put('/:date', (req, res) => {

    // update date

})

如果POST调用中已存在日期,我想重定向到PUT.使用res.redirect执行此操作的最佳方法是什么?

docs中,所有重定向都是针对不同的URL模式.我想保持URL相同,并将其余动词从POST更改为PUT.

我看了this SO问题,并在POST中添加了这一行:

res.redirect(303,’/:date’);

但它并没有将我重定向到PUT.

最佳答案 你在这里尝试做什么不会有几个原因,但舔你不需要做任何 – 见下文.

第一个问题

您在此处使用的303“See Other”重定向应始终跟随GET(或HEAD)请求,而不是PUT或其他任何内容.请参阅RFC 7231,第6.4.4节:

> https://tools.ietf.org/html/rfc7231#section-6.4.4

相关部分:

The 303 (See Other) status code indicates that the server is
redirecting the user agent to a different resource, as indicated by a
URI in the Location header field, which is intended to provide an
indirect response to the original request. A user agent can perform a
retrieval request targeting that URI (a GET or HEAD request if using
HTTP)
, which might also be redirected, and present the eventual result
as an answer to the original request. Note that the new URI in the
Location header field is not considered equivalent to the effective
request URI. [emphasis added]

第二个问题

其他流行的重定向类型 – 301“永久移动”和302“发现”在实践中通常与规范相反,好像它们是303“看到其他”,因此发出了GET请求.

维基百科上的List of HTTP status codes

This is an example of industry practice contradicting the standard. The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect (the original describing phrase was “Moved Temporarily”), but popular browsers implemented 302 with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307 to distinguish between the two behaviours. However, some Web applications and frameworks use the 302 status code as if it were the 303. [emphasis added]

第三个问题

有一个307临时重定向(自HTTP / 1.1以来),但它明确禁止更改HTTP方法,因此您只能将POST重定向到POST,PUT到PUT等,这有时可能有用,但在这种情况下不是 – 请参阅维基百科:

In this case, the request should be repeated with another URI; however, future requests should still use the original URI. In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request. For example, a POST request should be repeated using another POST request.

这个307重定向仍然不是你想要的,即使它是,但据我所知,它并不是普遍支持的,因此需要谨慎使用.

有关详细信息,请参阅此答案:

> Redirect POST to POST using Express JS routes

你的选择

您可以抽象出您的控制器 – 无论如何,您通常会做任何复杂的控制器:

// controllers - usually 'required' from a different file 
const update = (req, res) = {
  // update date
};
const add = (req, res) => {
  if (date exists) {
    return update(req, res);
  }
  // add to database
};

router.post('/:date', add);
router.put('/:date', update);

或者您可以将控制器的各个部分抽象为函数.

通用控制器

另请注意,您可以编写为每个可能在此处工作的HTTP方法调用的通用控制器:

router.use('/:date', (req, res) => {
});

休息

请注意,您在这里所做的并不是通常的REST方式来命名您的路径,在您的情况下,对于新的和更新的日期,仅使用PUT可能是有意义的.

与许多人认为PUT并不意味着UPDATE相反.它意味着将资源(新的或不是新的)放到某个URL(如果已存在则覆盖旧的URL).这就像在shell中编写它一样:

echo abc > /the/path/to/file.txt

如果文件存在,它将“更新”文件,但如果文件不存在,它也会创建一个新文件.

例如,如果你有/ users /:id路径,那么你使用:

> GET / users获取用户列表
> GET / users /:id以获取具有该ID的特定用户
> POST / user(不是/ users /:id)创建新用户而不提供ID
> PUT / users /:id覆盖现有用户或创建提供ID的新用户
> PATCH / users /:id用于更新具有该ID的用户提供的字段

在这里,据我所知你的:日期就像一个ID,即.如果记录已存在,则要覆盖该记录,如果该记录不存在则创建.在这两种情况下,您都提供:date path组件,因此您也可以在所有情况下使用PUT.

换句话说,您不能从一个HTTP方法重定向到另一个HTTP方法(GET除外),但在这种情况下您不需要这样做.

点赞