如何捕获后续的API签名?

时间:2017-04-15 20:12:16

标签: node.js express

我正在创建一个包含用户提供的路由的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/...

2 个答案:

答案 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/mehttp://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);