当存在路由匹配但没有HTTP方法匹配时,从express.js发送405
我正在寻找一种干净的方法,如果客户端发送的请求与映射的url路由匹配,但与映射的HTTP方法不匹配,则不允许使用我的express app return 405方法 我当前的实现是有一个默认的“catch all”处理程序,该处理程序尝试将url与注册路由相匹配,而忽略HTTP方法。如果存在匹配项,则我们知道返回405,否则我们让express执行其默认的404行为当存在路由匹配但没有HTTP方法匹配时,从express.js发送405,express,Express,我正在寻找一种干净的方法,如果客户端发送的请求与映射的url路由匹配,但与映射的HTTP方法不匹配,则不允许使用我的express app return 405方法 我当前的实现是有一个默认的“catch all”处理程序,该处理程序尝试将url与注册路由相匹配,而忽略HTTP方法。如果存在匹配项,则我们知道返回405,否则我们让express执行其默认的404行为 我希望有一种更好的方法,不需要运行所有的路由匹配两次(一次由express运行,一次由我的处理程序运行)。由于模糊性,实在没有其他
我希望有一种更好的方法,不需要运行所有的路由匹配两次(一次由express运行,一次由我的处理程序运行)。由于模糊性,实在没有其他方法。就我个人而言,我会这样做:
var route = '/page/:id/comments'
app.get(route, getComments)
app.all(route, send405)
function send405(req, res, next) {
var err = new Error()
err.status = 405
next(err)
}
无论哪种方式,您都必须检查两次路由。以下是我在多个Django应用程序中成功使用的方法,现在在Node和Express中使用。下面还介绍了关于HTTP 405的以下内容: 响应必须包括一个Allow标头,其中包含一个有效响应列表 请求的资源的方法 因此,关键点是将请求路由到同一个处理程序,而不考虑方法
app.all('/page/:id', page.page);
app.all('/page/:id/comments', page.comments);
app.all('/page/:id/attachments', page.attachments);
...
下一点是验证处理程序函数“comments”中的方法。请注意,处理程序负责处理所有方法。在Django的世界中,这是唯一的方法,因为框架迫使您将URL的路由与对URL所代表的资源执行的实际操作分开
在处理程序中,您可以检查如下方法
exports.comments = function (req, res) {
if (req.route.method === 'get') {
res.send(200, 'Hello universe.');
} else {
res.set('Allow', 'GET');
res.send(405, 'Method Not Allowed');
}
}
…但正如您所预料的那样,代码将很快变得重复且不好读,特别是当您有许多处理程序函数和许多不同的允许方法集时
因此,我为该作业准备了一个名为restful的快捷函数。在任何需要的地方定义函数。我个人会把它放在helpers.js中,放在实现处理函数的同一目录下
var restful = function (req, res, handlers) {
//
// This shortcut function responses with HTTP 405
// to the requests having a method that does not
// have corresponding request handler. For example
// if a resource allows only GET and POST requests
// then PUT, DELETE, etc requests will be responsed
// with the 405. HTTP 405 is required to have Allow
// header set to a list of allowed methods so in
// this case the response has "Allow: GET, POST" in
// its headers [1].
//
// Example usage
//
// A handler that allows only GET requests and returns
//
// exports.myrestfulhandler = function (req, res) {
// restful(req, res, {
// get: function (req, res) {
// res.send(200, 'Hello restful world.');
// }
// });
// }
//
// References
//
// [1] RFC-2616, 10.4.6 405 Method Not Allowed
// https://tools.ietf.org/html/rfc2616#page-66
//
// [2] Express.js request method
// http://expressjs.com/api.html#req.route
//
var method = req.route.method; // [2]
if (!(method in handlers)) {
res.set('Allow', Object.keys(handlers).join(', ').toUpperCase());
res.send(405);
} else {
handlers[method](req, res);
}
}
使用restful,现在自动处理405个响应并设置适当的Allow头非常轻松。只需为您允许的每个方法提供一个函数,其余的由restful完成
因此,让我们修改前面的示例:
exports.comments = function (req, res) {
restful(req, res, {
get: function (req, res) {
res.send(200, 'Hello restful universe.');
}
});
}
为什么叫restful?在web中,API必须遵守一些约定,如使用HTTP 405响应具有不受支持方法的请求。在需要时,这些约定中的许多可以集成到restful中。因此,名称是restful,而不是类似于auto405或http405handler的名称
希望这有帮助。有什么想法吗?这是一个老问题,但我是这么做的。我只是把它放在我所有的路线之后,但在我的400处理器之前
// Handle 405 errors
app.use(function(req, res, next) {
var flag = false;
for (var i = 0; i < req.route.stack.length; i++) {
if (req.method == req.route.stack[i].method) {
flag = true;
}
}
if (!flag) {
err = new Error('Method Not Allowed')
err.status = 405;
return next(err)
}
next();
});
//处理405个错误
应用程序使用(功能(请求、恢复、下一步){
var标志=假;
对于(变量i=0;i
方法1:使用.route()
和.all()
//您的路由处理程序
const handlers=require(`./handlers.js`);
//405处理器
const methodNotAllowed=(req,res,next)=>res.status(405.send();
路由器
.路线(`/products`)
.get(handlers.getProduct)
.put(handlers.addProduct)
.所有(不允许使用的方法)代码>我一直这样做:
假设您有/
的GET和POST方法处理程序。您可以使用app.route
或router.route
包装路径,并相应地分配处理程序
app.route("/").get((req, res) => {
/* DO SOMETHING*/
}).post((req, res) => {
/* DO SOMETHING*/
}).all((req, res) => {
res.status(405).send();
});
请求将与路由匹配,并通过处理程序进行过滤。如果存在处理程序,它将像往常一样得到处理。否则,它将到达将状态代码设置为405并结束请求的all
处理程序 我是这样修复的:
/*paths here*/
router.get('/blah/path1', blah.do_something );
router.post('/blah/path2', blah.do_something_else );
/* if we get here we haven't already gone off down another path */
router.all('/*', (req,res) => { res.status(405),
res.json({'status':405,
'message':req.method + ' not allowed on this route'})
});
/* simples */
谢谢,你的建议很有意义,而且比我现在做的要好。这个解决方案不是可行的。关于HTTP 405说:“响应必须包含一个Allow标头,其中包含请求资源的有效方法列表。”解决方案无法提供该列表,因此不应视为有效。检查我的答案,寻找更合适的方法。似乎是烘焙框架本身的最佳选择。为了让它在Express 4中工作,我必须更改var method=req.route.method代码>到var方法=(req.method | |“”).toLowerCase()
Express不推荐的res.send(status,body):使用res.status(status).send(body)代替,但是为什么不使用.all()
?和Allow
标题也应该有标题,因为我相信这只适用于较旧版本的Express。现在路由方法大不相同了。HTTP 405响应必须有Allow
头。如何区分404和405。这解决了一个问题,但产生了一个更大的问题作为副作用。这些示例中的任何一个的可能重复实际上都无效,因为具有405状态的响应必须具有带有允许方法的标题“Accept”。