使用相同的网址

时间:2018-02-25 17:48:10

标签: javascript node.js rest express routes

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

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

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

})

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

    // update date

})

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

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

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

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

但它没有将我重定向到PUT

1 个答案:

答案 0 :(得分:1)

你在这里尝试做什么不会有多种原因,但是你不需要做任何事情 - 见下文。

第一个问题

303"见其他"您在此处使用的重定向,规范应始终跟随GET(或HEAD)请求,而不是PUT或其他任何内容。参见RFC 7231,第6.4.4节:

相关部分:

  

303(请参阅其他)状态代码表示服务器是   将用户代理重定向到不同的资源,如a所示   Location头字段中的URI,用于提供   对原始请求的间接响应。 用户代理可以执行   针对该URI的检索请求(如果使用,则为GET或HEAD请求)   HTTP),也可能被重定向,并显示最终结果   作为原始请求的答案。注意,新的URI在   位置标题字段不被视为等效于有效   请求URI。 [强调补充]

第二个问题

其他流行的重定向类型 - 301"永久移动"和302"发现"在实践中,通常工作违反规范,好像他们是303"见其他"因此发出GET请求。

请参阅维基百科上的List of HTTP status codes

  

这是符合标准的行业惯例的一个例子。 HTTP / 1.0规范(RFC 1945)要求客户端执行临时重定向(原始描述短语是"暂时移动"),但流行的浏览器实现302具有303 See Other的功能。因此,HTTP / 1.1添加了状态代码303和307来区分这两种行为。但是,一些Web应用程序和框架使用302状态代码,就好像它是303. [强调添加]

第三个问题

有一个307临时重定向(自HTTP / 1.1以来),但它明确禁止更改HTTP方法,因此您只能将POST重定向到POST,PUT到PUT等,这有时可能有用但不在此案例 - 见维基百科:

  

在这种情况下,请求应该使用另一个URI重复;但是,未来的请求仍应使用原始URI。与历史上实施302的方式相反,重新发出原始请求时,不允许更改请求方法。例如,应使用另一个POST请求重复POST请求。

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

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

您的选择

你可以抽象出你的控制器 - 无论如何你通常会做什么,对于任何复杂的事情:

// 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

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

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

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

将更新"该文件是否存在,但如果文件不存在,它也会创建一个新文件。

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

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

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

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