webentwicklung-frage-antwort-db.com.de

Umgang mit fehlerhafter JSON.parse () im Node sicher

Verwenden von node/express - Ich möchte einige JSON-Header aus den Anforderungsheadern entfernen, aber ich möchte dies sicher tun.
Wenn es aus irgendeinem Grund kein gültiger JSON ist, ist es in Ordnung, es kann einfach falsch oder was auch immer zurückgegeben werden und es wird einfach die Anfrage ablehnen und weitermachen. Das Problem ist, dass es einen Syntaxfehler auslöst, wenn es kein gültiges JSON ist. Normalerweise möchte ich einen Syntaxfehler in die Luft jagen, aber in diesem Fall nicht.

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

Kratze ich den Stack und überprüfe, ob von diesem bestimmten Modul ein ungültiger Parser-Aufruf vorliegt, und ignoriere er ihn, wenn dies der Fall ist? Das scheint ein bisschen verrückt zu sein. Sicher gibt es einen besseren Weg.

BEARBEITEN: Ich bin mir bewusst, dass try/catch-BlöckeEINEMethode zur Behandlung dieses Fehlers sind, aber ist es die beste Methode in einer Node-App? Wird auf diese Weise der Knoten blockiert?

22
tpie

Der beste Weg, ungültige JSON-Parsing-Fehler abzufangen, besteht darin, die Aufrufe von JSON.parse() in einen try/catch-Block zu setzen.

Sie haben wirklich keine andere Option - die integrierte Implementierung löst eine Ausnahme für ungültige JSON-Daten aus. Die einzige Möglichkeit, um zu verhindern, dass diese Ausnahme Ihre Anwendung stoppt, besteht darin, sie abzufangen. Selbst die Verwendung einer Drittanbieter-Bibliothek wird dies nicht vermeiden - sie müssen irgendwo einen try/catch für einen JSON.parse()-Aufruf ausführen.

Die einzige Alternative besteht darin, einen eigenen JSON-Parsing-Algorithmus zu implementieren, der ungültigere Datenstrukturen eher verzeihen könnte, sich aber wie ein 1-Kubikmeter-Loch mit einer kleinen Nuke anfühlt.

Hinweis zur Leistung

Die von Node.js verwendete v8-JavaScript-Engine kann -Funktionen nicht optimieren, die einen try/catch-Block enthalten. 

Update:v8 4.5 und höher können try/catch optimieren. Für ältere Versionen siehe unten.

Eine einfache Problemumgehung besteht darin, die sichere Parsing-Logik in eine separate Funktion zu integrieren, sodass die Hauptfunktion noch optimiert werden kann:

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!
}

Wenn das JSON-Parsing sporadisch durchgeführt wird, hat dies möglicherweise keine merkliche Auswirkung auf die Leistung, aber bei unsachgemäßer Verwendung in der belastungsintensiven Funktion kann dies zu einer drastischen Erhöhung der Antwortzeiten führen.

Beachten Sie, dass Try/Catch blockiert wird

Es ist zu beachten, dass every.single.statement des JavaScript-Codes in Node.js nur einmal ausgeführt wird, unabhängig davon, ob er von der Hauptfunktion oder von einem Rückruf oder von einem Aufruf aufgerufen wird anderes Modul oder was auch immer. Somit wird jede einzelne Anweisung blockiert den Prozess. Dies ist nicht unbedingt eine schlechte Sache - eine gut konzipierte Anwendung muss die meiste Zeit auf eine externe Ressource warten (Datenbankantwort, HTTP-Kommunikation, Dateisystemoperationen usw.). Es ist daher von großer Bedeutung, dass häufig ausgeführter JavaScript-Code von der V8-Engine optimiert werden kann, sodass in diesem gesperrten Zustand so wenig Zeit wie möglich benötigt wird - siehe Hinweis zur Leistung.

49
Robert Rossmann

Sie können try und catch verwenden.

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

Der Standardversuch try/catch ist die richtige Methode, um einen JSON.parse-Fehler in node.js zu behandeln, wie in den Knoten Produktionspraktiken für die Fehlerbehandlung docs der joyent-Website erwähnt.

... Der einzige häufig verwendete Fall, in dem Sie try/catch verwenden würden, ist JSON.parse und andere vom Benutzer eingegebene Validierungsfunktionen.

Das stimmt auch mit der Verbindung zu nodejitsu überein, die Aleksandr in seinem Kommentar angegeben hat.

3
tpie

Es geht darum, das Skript während einer Ausnahme nicht zu brechen

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;

Nun, das hat für mich funktioniert. In Catch habe ich die Daten konvertiert, bevor sie in JSON analysiert wurden.

0
Ganesh Todkar