我正在创建一个包含用户提供的路由的API服务器。如果先前的路由与用户的令牌匹配,我怎么能写出用户定义的路由被动态处理的路由。
我尝试了两种方法,一种方法:params
,但由于用户可能输入多级路线,因此无法正常工作。
router.all('/api/:apikey/:fakeapi', function (req, res, next) {
logger.debug(`API Key: ${req.params.apikey}, Requested URL: ${req.params.fakeapi}`);
res.send(`API Key: ${req.params.apikey}, Requested URL: ${req.params.fakeapi}`);
});
以上代码,如果路由/api/378929832/fine
有效,但当路由类似api/378929832/fine/with/me
时失败。
如果先前的API签名与之匹配,如何使其处理所有后续/xyz/xyz/xyz/...
?
答案 0 :(得分:0)
我提出了一个hacky解决方案,但这不是最好的方法,所以我问了上面的问题。
我已经使用*
让它在先例匹配后捕获所有内容,如下面的
router.all('/api/:apikey/*', function (req, res, next) {
logger.debug(`API Key: ${req.params.apikey}, Requested URL: ${req.url.replace('/api/', '').replace(req.params.apikey + '/', '')}`);
res.send(`API Key: ${req.params.apikey}, Requested URL: ${req.url.replace('/api/', '').replace(req.params.apikey + '/', '')}`);
});
以上代码适用于http://localhost:8080/api/378929832/fine
以及任何动态http://localhost:8080/api/378929832/fine/with/me
或http://localhost:8080/api/378929832/fine/with/me/?redirect=http://stackoverflow.com
。
答案 1 :(得分:0)
首先,只需要了解路线的设计 - RESTful API design就是风靡一时,尝试以RESTful方式设计API非常棒。它在逻辑上是有道理的,并且现在通常期望Web服务。即使您只是在内部使用它,它也可以通过强制执行整个路由的一致性来简化您的工作,并且如果您想要向外部世界开放API,则意味着它可以随时使用。如果您已经构建了一个供外部消费的API,那么不遵循最佳实践就会让您的开发人员受到伤害!
直接向我伸出的东西是API密钥作为路径的一部分。路由通常写为/api/[object or resource]
,因此从那个角度来看,在那里抛出API密钥是没有意义的。更重要的是,要求URL中的密钥意味着每个API密钥都将显示在Web服务器的日志中。如果您将其更改为查询字符串参数,则也会遇到此问题,因此一个好的选项通常是在标头中包含API密钥或其他身份验证令牌(授权标头通常与令牌一起使用)。
接下来,如果您希望继续使用当前格式,可以使用router.param()
。
router.param
获取路由参数的名称以及当后续路由显示该参数时将调用的函数。这意味着无论何时显示在路径中,您都可以捕获并检查API密钥,而无需明确指定它。
例如:
var checkApiKey = function(req, res, next, id) {
// `id` is the parameter that was passed
if(!isValidApiKey(id)) return res.send("Bad");
return next();
}
router.param("apikey",routes.checkApiKey);
router.get("/:apikey/me",routes.listMe);
router.post("/:apikey/me",routes.createMe);
如果你有一个父路由器,你可以移动一些东西:apikey只在root指定一次,所有API请求的基数为/api/[key]/
。功能相同,这只是意味着你没有复制每条路线的:apikey参数:
var apiRouter = express.Router();
apiRouter.get("/me",listMe);
apiRouter.post("/me",createMe);
parentRouter.param("apikey",checkApiKey);
parentRouter.use("/api/:apikey",apiRouter);
我发现您的重点是在API密钥之后获取请求的路由,该密钥根据用户而变化。这可以通过父路由器轻松完成,如下所示:
var parseUserApiRoute = function(req, res, next) {
// req.path contains the URL after /api/:apikey
// e.g. For a request to /api/abcdef/this/is/my/route, req.path will be /this/is/my/route
res.send("Path: "+req.path);
}
var checkApiKey = function () {...};
var apiRouter = express.Router();
apiRouter.get("*",parseUserApiRoute);
parentRouter.param("apikey",checkApiKey)
parentRouter.use("/api/:apikey",apiRouter);