验证node.js中REST api请求的查询参数

时间:2019-04-03 14:52:49

标签: javascript node.js rest

对于针对GET请求的每种对象类型,我都有一个有效查询参数的对象。

var queryFields = {
  'organisation': ['limit', 'page', 'id', 'search'],
  'actor': ['limit', 'page', 'id', 'search'],
  'version': ['limit', 'page', 'search'],
  'product': ['limit', 'page', 'search', 'id', 'type', 'brand', 'model', 'manufacturerSpid'],
  'asset': ['limit', 'page', 'search', 'order', 'sort', 'id', 'name', 'currentCustodianSpid', 'currentLocationSpid', 'productSpid', 'search'],
  'location': ['limit', 'page', 'search', 'id'],
  'workorder': ['limit', 'page', 'search', 'id', 'type', 'status', 'requirementSpid', ],
  'move': ['limit', 'page', 'search'],
  'transfer': ['limit', 'page', 'search'],
  'requirement': ['limit', 'page', 'search', 'id', 'type', 'source', 'productSpid', 'status', ],
  'artefact': ['limit', 'page', 'search'],
  'attestation': ['limit', 'page', 'search'],
};

我想使用此功能来确保仅接受这些有效参数的请求。现在,promise使用有效,无效或0参数解析false。我过滤的方式似乎有问题。我传入对象类型和请求。如果请求包含查询参数,我想从对象中获取有效参数,并检查req中的参数是否都与对象中的参数有效匹配。如果有任何无效的,我想解决false。如果没有参数,我要解析true。如果只有有效的参数,我想解析true。我可以对此功能进行一些调整以获得该结果吗?

function getQueryFields(object) {
  if (utils.isDefined(queryFields[object])) return queryFields[object];
  return [];
}

function fieldValidator (objType, req) {
  return new Promise(function(resolve) {
    if (utils.isDefined(req.query)) {
      var fields = getQueryFields(objType);
      //Only resolve true with valid fields
      fields = fields.filter(function(field) { return Object.keys(req.query).indexOf(field) > -1;});
      if (Object.keys(req.query) !== Object.keys(fields)) {
        resolve(false);
      } else {
        resolve (true);
      }
    } else {
      resolve(true);
    }
  });
}

3 个答案:

答案 0 :(得分:1)

您的功能存在一些问题。我想先解决第一个问题,然后再讨论您的实际问题,因为这将使清晰度大大提高。首先:您不需要Promises,这是一个同步功能。

重写#1:

function getQueryFields(object) {
  if (utils.isDefined(queryFields[object])) return queryFields[object];
  return [];
}

function fieldValidator (objType, req) {
  if (utils.isDefined(req.query)) {
    var fields = getQueryFields(objType);
    //Only resolve true with valid fields
    fields = fields.filter(function(field) {
      return Object.keys(req.query).indexOf(field) > -1;
    });
    if (Object.keys(req.query) !== Object.keys(fields)) {
      return false;
    } else {
      return true;
    }
  }
} else {
  return true;
}

此函数可以使用的另一件事是“提前”返回。这样可以更轻松地跟踪正在发生的事情并减少分支的数量:

重写#2:

function fieldValidator (objType, req) {
  if (req.query === undefined) {
    return true;
  }

  var fields = getQueryFields(objType);
  //Only resolve true with valid fields
  fields = fields.filter(function(field) {
    return Object.keys(req.query).indexOf(field) > -1;
  });
  return (Object.keys(req.query) === Object.keys(fields));
}

这些都不能回答您的问题,但我需要它来使您在做的事情更加清晰=)

问题实际上在于比较Object.keys()Object.keys()返回一个迭代器,但是它返回的每个迭代器都是唯一的。

Javascript中的对象无法真正按“值”进行比较。按值比较对象的唯一方法是逐个检查其键。

由于您希望属性完全匹配 ,因此我想将其更改为:

  1. 检查您是否具有相同数量的查询参数。
  2. 检查是否传递的每个查询参数都出现在有效查询参数集中。

基于此,我认为这将是我的版本:

function fieldValidator(objType, req) {
  if (!req.query || Object.keys(req.query).length === 0) {
    // Covers the 'undefined' and 'empty object' case
    return true;
  }

  const fields = getQueryFields(objType);
  const keys = Object.keys(req.query);

  // Do we have enough query parameters?
  if (keys.length !== fields.length) return false;

  // Does every query parameter appear in the list?
  for(const key of keys) {
     if (!fields.includes(key)) return false;
  }
  return true;
}

答案 1 :(得分:0)

“字段”是键名的数组。您正在对照键名数组的对象键检查req.query键的数组。那就是数组的索引,只是连续的整数["0", "1", "2", ... etc]。更不用说,您正在两个数组之间进行不等式检查,除非引用相同,否则这将永远是不正确的,否则它们将不在此处。因此,当然,第一个条件始终会失败并解析为false。在控制台中尝试一下:[1, 2, 3] === [1, 2, 3]将为假(与宽松的相等性检查相同),因为它们是恰好具有相同条目的不同对象。

因此,我认为一个更好的方法是更改​​过滤器,以便过滤掉列表中的每个查询字段,并确保最终数组中没有条目(因为剩下的任何内容都是与列表不匹配的键)

  fields = Object.keys(req.query).filter(function(field) { return fields.indexOf(field) > -1;});
  if (fields.length > 0) {
    resolve(false);
  } else {
    resolve (true);
  }

(我假设您有一个使用Promise的原因,如果没有,那么我会赞同Marcos Casagrande的建议,彻底摆脱Promise并直接从函数中返回true或false。)< / p>

答案 2 :(得分:0)

如果使用expressjs,有一种使用check api的好方法。

https://express-validator.github.io/docs/check-api.html