web-dev-qa-db-fra.com

node.js distinguant les erreurs lors de la requête http

Mon application node.js utilise http.request à REST API http://army.gov/launch-nukes et je dois distinguer trois cas possibles:

  • Success - Le serveur répond par l'affirmative. Je sais que mes ennemis sont détruits.
  • Failure - Soit j'ai reçu une erreur du serveur, ou je n'ai pas pu me connecter au serveur. J'ai toujours des ennemis.
  • Unknown - Après avoir établi une connexion au serveur, j'ai envoyé la demande - mais je ne sais pas ce qui s'est passé. Cela pourrait signifier que la demande n'a jamais été envoyée au serveur ou que la réponse du serveur n'a jamais été envoyée. Je viens peut-être ou non de commencer une guerre mondiale.

Comme vous pouvez le voir, il est très important pour moi de distinguer le cas Failure et Unknown, car ils ont des conséquences très différentes et des actions différentes que je dois prendre.

J'aimerais aussi beaucoup utiliser http Keep-Alive - car que puis-je dire, je suis un peu un belliciste et je prévois de faire beaucoup de demandes en rafales (et puis rien pendant de longues périodes)

-

Le cœur de la question est de savoir comment séparer une erreur de connexion/délai d'expiration (qui est un Failure) d'une erreur/délai d'expiration qui se produit après que la demande a été placée sur le câble (qui est un Unknown).

Dans la logique du pseudo-code, je veux ceci:

var tcp = openConnectionTo('army.gov') // start a new connection, or get an kept-alive one
tcp.on('error', FAILURE_CASE);
tcp.on('connectionEstablished',  function (connection) {

       var req = connection.httpGetRequest('launch-nukes');
       req.on('timeout', UNKNOWN_CASE);
       req.on('response', /* read server response and decide FAILURE OR SUCCESS */);
   }
)
24
Heptic

Voici un exemple:

var http = require('http');

var options = {
  hostname: 'localhost',
  port: 7777,
  path: '/',
  method: 'GET'
};

var req = http.request(options, function (res) {
  // check the returned response code
  if (('' + res.statusCode).match(/^2\d\d$/)) {
    // Request handled, happy
  } else if (('' + res.statusCode).match(/^5\d\d$/))
    // Server error, I have no idea what happend in the backend
    // but server at least returned correctly (in a HTTP protocol
    // sense) formatted response
  }
});

req.on('error', function (e) {
  // General error, i.e.
  //  - ECONNRESET - server closed the socket unexpectedly
  //  - ECONNREFUSED - server did not listen
  //  - HPE_INVALID_VERSION
  //  - HPE_INVALID_STATUS
  //  - ... (other HPE_* codes) - server returned garbage
  console.log(e);
});

req.on('timeout', function () {
  // Timeout happend. Server received request, but not handled it
  // (i.e. doesn't send any response or it took to long).
  // You don't know what happend.
  // It will emit 'error' message as well (with ECONNRESET code).

  console.log('timeout');
  req.abort();
});

req.setTimeout(5000);
req.end();

Je vous recommande de jouer avec Netcat, c'est-à-dire:

$ nc -l 7777
// Just listens and does not send any response (i.e. timeout)

$ echo -e "HTTP/1.1 200 OK\n\n" | nc -l 7777
// HTTP 200 OK

$ echo -e "HTTP/1.1 500 Internal\n\n" | nc -l 7777
// HTTP 500

(etc...)

33
kamituel

Cela se trouve généralement dans le code d'état des API. Dans le package de demande, vous pouvez y accéder comme ceci

request('http://www.google.com', function (error, response, body) {
   if (!error && response.statusCode == 200) {
       console.log(body) // Print the google web page.
   }
})

response.statusCode étant 200 signifie que cela a fonctionné. 500 serait un échec. Inconnu serait le rappel jamais appelé.

Si l'API que vous décrivez ne suit pas les codes de réponse standard, je ne sais pas. Vous devrez regarder les documents.