在我的快递应用程序中,我有两条路线如下:
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
。
答案 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方式来命名您的路径,并且在您的情况下仅对新的和更新的日期使用PUT可能是有意义的。
与许多人认为的相反 PUT并不意味着更新。它意味着将资源(新的或不是新的)放到某个URL(如果已存在则覆盖旧的URL)。它非常像在shell中写这个:
echo abc > /the/path/to/file.txt
将更新"该文件是否存在,但如果文件不存在,它也会创建一个新文件。
例如,如果你有/ users /:id路径,那么你使用:
在这里,我理解你的:日期就像一个ID,即。如果记录已存在,则要覆盖记录,如果记录不存在则创建。 在这两种情况下,您都提供:日期路径组件,因此您也可以在所有情况下使用PUT。
换句话说,您无法从一种HTTP方法重定向到另一种HTTP方法(GET除外),但在这种情况下您不需要这样做。