如何捕获随后的API签名



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

我提出了一个黑客解决方案,但这不是最好的方法,所以我问过上述问题。

我已经使用 *在先例匹配之后将其全部捕获,例如以下

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

首先,只是在路线的设计上提起一个问题 - 静止的API设计风靡一时,试图以宁静的方式设计您的API可能很棒。这在逻辑上是有道理的,如今通常对Web服务期望。即使您仅在内部使用它,它也可以通过在您的路线上执行一致性来真正简化事物,这意味着如果您想向外界打开API,则可以使用它。如果您已经建立了用于外部消费的API,那么不遵循最佳实践会为您的开发人员带来受伤的世界!

立即引起我的事情是API键作为路径的一部分。路线通常以/api/[object or resource]的形式写,因此从这个角度来看,将API键投入其中是没有意义的。更重要的是,需要URL中的密钥意味着每个API密钥将在您的Web服务器日志中显示。如果将其更改为查询字符串参数,您也将遇到此问题,因此一个不错的选择是在标题中使用API键或其他auth令牌(授权标头通常与令牌一起使用(。

继续前进,如果您渴望继续使用当前格式,则可以使用router.param()

router.param获取路由参数的名称以及当随后的路由显示该参数时将调用的函数。这意味着您可以在API密钥出现在路线中时捕获并检查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仅以根本指定一次,并且所有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键之后获得所请求的路由,该路由根据用户而变化。您可以使用父Router轻松完成此操作,例如:

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);

最新更新