Проверка параметров запроса для запросов REST API в node.js - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть объект допустимых параметров запроса для каждого типа объекта для запроса GET к API.

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'],
};

Я хочу использовать эту функцию, чтобы убедиться, что только эти действительные параметры принимаются для запроса. Сейчас обещание разрешает false с допустимыми, недействительными или 0 параметрами. Кажется, проблема с тем, как я фильтрую. Я передаю в тип объекта и запрос. Если в запросе есть параметры запроса, я хочу получить действительные параметры объекта и проверить, что все параметры в 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);
    }
  });
}

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

Есть несколько проблем с вашей функцией. Я хочу исправить первые проблемы, прежде чем приступить к вашей реальной проблеме, потому что это немного увеличит ясность. Первое: вам не нужны обещания, это синхронная функция.

Переписать # 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;
}
0 голосов
/ 03 апреля 2019

«Поля» - это массив имен ключей. Вы проверяете массив ключей req.query для ключей объекта массива имен ключей. Это индексы массива, просто последовательные целые числа, ["0", "1", "2", ... etc]. Не говоря уже о том, что вы делаете проверку неравенства между двумя массивами, что никогда не будет правдой, если ссылки не совпадают, чего они здесь не имеют. Поэтому, конечно, это первое условие всегда терпит неудачу и становится ложным. Попробуйте сами в консоли: [1, 2, 3] === [1, 2, 3] будет иметь значение false (то же самое с непроверенными проверками равенства), потому что это разные объекты, которые просто имеют одинаковые записи.

Так что я думаю, что лучший подход - это изменить ваш фильтр так, чтобы он отфильтровывал все поля запроса в списке и гарантировал, что в конечном массиве нет записей (поскольку все, что осталось, будет ключом, который не соответствует списку) .

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

(Я предполагаю, что у вас есть неописуемая причина для использования Обещания; если нет, то я бы согласился с предложением Маркоса Касагранде полностью избавиться от Обещания и просто вернуть true или false из функции напрямую.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...