it-swarm.com.ru

Безопасная обработка плохого JSON.parse () в узле

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

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

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

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

22
tpie

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

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

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

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

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

Update:v8 4.5 и выше могут оптимизировать try/catch . Более старые версии см. Ниже.

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

function safelyParseJSON (json) {
  // This function cannot be optimised, it's 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, поэтому в этом заблокированном состоянии требуется как можно меньше времени - см. Примечание о производительности.

49
Robert Rossmann

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

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

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

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

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

3
tpie

Это о том, как не сломать скрипт во время исключения

Promise.resolve((body)=>{
            let fbResponse = JSON.parse(body);
            // some code for good
        }).catch(error => {
            cl('Parsing error:');
            cl(error);
            // some code for bad
        });
0
user3640561
        var parsed;

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

        root = parsed;

Ну, это сработало для меня .... В Catch я преобразовал данные в stringify перед их анализом в JSON.

0
Ganesh Todkar