Подтвердить что ты не робот

Работа с плохим JSON.parse() в node безопасно

Использование node/express - Я хочу получить некоторые JSON из заголовков запросов, но я хочу сделать это безопасно.
Если по какой-то причине он недействителен JSON, это нормально, он может просто вернуть ложь или что-то еще, и он просто отклонит запрос и продолжит работу. Проблема заключается в том, что она выдает синтаксическую ошибку, если она недействительна JSON. Обычно я хочу, чтобы синтаксическая ошибка взорвалась, но не в этом случае.

var boom = JSON.parse(req.headers.myHeader);

Я очищаю стек и проверяю плохой вызов синтаксического разбора с этого конкретного модуля, и, если это так, он игнорирует его? Это кажется немного сумасшедшим. Конечно, лучший способ.

EDIT: Я знаю, что блоки try/catch - это A способ обработки этой ошибки, но лучший ли это в приложении node? Будет ли этот способ блокировать node?

4b9b3361

Ответ 1

Лучший способ уловить неверные ошибки разбора JSON - это перевести вызовы на JSON.parse() в блок try/catch.

У вас действительно нет другого варианта - встроенная реализация генерирует исключение из недопустимых данных JSON, и единственный способ предотвратить это исключение от остановки приложения - это поймать его. Даже использование сторонней библиотеки не позволит избежать этого - они должны сделать try/catch при вызове JSON.parse() где-нибудь.

Единственная альтернатива - реализовать собственный алгоритм синтаксического анализа JSON, который может быть более прощающим в отношении недействительных структур данных, но это похоже на то, чтобы выкапывать отверстие в 1 кубический метр с небольшим ядерным оружием.

Примечание о производительности

JavaScript-движок v8, используемый Node.js не может оптимизировать функции, содержащие блок try/catch.

Обновление: v8 4.5 и выше может оптимизировать try/catch. Для более старых версий см. Ниже.

Простым обходным решением является включение логики безопасного анализа в отдельную функцию, чтобы можно было оптимизировать основную функцию:

function safelyParseJSON (json) {
  // This function cannot be optimised, it best to
  // keep it small!
  var parsed

  try {
    parsed = JSON.parse(json)
  } catch (e) {
    // Oh well, but whatever...
  }

  return parsed // Could be undefined!
}

function doAlotOfStuff () {
  // ... stuff stuff stuff
  var json = safelyParseJSON(data)
  // Tadaa, I just got rid of an optimisation killer!
}

Если разбор JSON выполняется спорадически, это может не иметь заметного влияния на производительность, но если его использовать ненадлежащим образом в функции интенсивного использования, это может привести к резкому увеличению времени отклика.

Примечание о блокировке try/catch

Следует отметить, что every.single.statement кода JavaScript в Node.js выполняется только один раз, независимо от того, вызвал ли он основную функцию или от обратного вызова или от другого модуля или чего-то еще. Таким образом, каждый оператор блокирует процесс. Это не обязательно плохо - хорошо спроектированное приложение будет тратить большую часть своего времени на ожидание внешнего ресурса (ответ базы данных, HTTP-связь, операции с файловой системой и т.д.). Поэтому очень важно, что часто исполняемый код JavaScript может быть оптимизирован движком v8, поэтому в этом заблокированном состоянии требуется как можно меньше времени - см. Примечание о производительности.

Ответ 2

Вы можете использовать try и catch

function parseMyHeader(){
    try {
      return JSON.parse(req.headers.myHeader);
    } catch(ex){
      return null;
    }
}

Ответ 3

Стандартный try/catch - это правильный способ обработки ошибки JSON.parse в node.js, как указано в node производственной практике для обработки ошибок с радостного веб-сайта, в котором говорится:

... единственным обычным случаем, когда вы используете try/catch, является JSON.parse и другие функции проверки ввода пользователем.

Это также согласуется со ссылкой на nodejitsu, которую Александр поставил в своем комментарии.

Ответ 4

        var parsed;

        try {
            parsed = JSON.parse(data);
        } catch (e) {
            parsed = JSON.parse(JSON.stringify(data));
        }

        root = parsed;

Хорошо, это сработало для меня. В Catch я преобразовал данные в строковое выражение, прежде чем разбирать его в JSON.