web-dev-qa-db-ja.com

リクエストパイピングのエラー処理

私はnodejsでシンプルなプロキシを書いて、それは次のようになります

var request = require( 'request' );
app.all( '/proxy/*', function( req, res ){
    req.pipe( request({
        url: config.backendUrl + req.params[0],
        qs: req.query,
        method: req.method
    })).pipe( res );
});

リモートホストが使用可能な場合は正常に動作しますが、リモートホストが使用できない場合は、ノードサーバー全体が未処理の例外でクラッシュします。

stream.js:94                                               
      throw er; // Unhandled stream error in pipe.         
            ^                                              
Error: connect ECONNREFUSED                                
    at errnoException (net.js:901:11)                      
    at Object.afterConnect [as oncomplete] (net.js:892:19) 

そのようなエラーをどのように処理できますか?

24
ioncreature

ドキュメント( https://github.com/mikeal/request )を見ると、次の行に沿って何かを実行できるはずです。

たとえば、リクエストに応じてオプションのコールバック引数を使用できます。

app.all( '/proxy/*', function( req, res ){
  req.pipe( request({
      url: config.backendUrl + req.params[0],
      qs: req.query,
      method: req.method
  }, function(error, response, body){
    if (error.code === 'ECONNREFUSED'){
      console.error('Refused connection');
    } else { 
      throw error; 
    }
  })).pipe( res );
});

または、次のようなキャッチされていない例外をキャッチすることもできます。

process.on('uncaughtException', function(err){
  console.error('uncaughtException: ' + err.message);
  console.error(err.stack);
  process.exit(1);             // exit with error
});
32
Tom Grant

ECONNREFUSEDのキャッチされない例外をキャッチした場合は、プロセスを再起動してください。テストで、例外を無視して単純に再接続しようとすると、ソケットが不安定になることがわかりました。

ここに素晴らしい概要があります: http://shapeshed.com/uncaught-exceptions-in-node/

次のコードを使用して、「forever」ツールを使用してノードプロセスを再起動しました。

process.on('uncaughtException', function(err){
//Is this our connection refused exception?
  if( err.message.indexOf("ECONNREFUSED") > -1 )
  {
    //Safer to shut down instead of ignoring
    //See: http://shapeshed.com/uncaught-exceptions-in-node/
    console.error("Waiting for CLI connection to come up. Restarting in 2 second...");
    setTimeout(shutdownProcess, 2000); 
  }
  else
  {
   //This is some other exception.. 
   console.error('uncaughtException: ' + err.message);
   console.error(err.stack);
   shutdownProcess();
  }
});

//Desc: Restarts the process. Since forever is managing this process it's safe to shut down
//      it will be restarted.  If we ignore exceptions it could lead to unstable behavior.
//      Exit and let the forever utility restart everything
function shutdownProcess()
{
  process.exit(1); //exit with error
}
2
bschwagg

実際には、ECONNREFUSED例外がキャッチされないようにする必要があります。

var request = require( 'request' );
app.all( '/proxy/*', function( req, res ){
    req.pipe( request({
        url: config.backendUrl + req.params[0],
        qs: req.query,
        method: req.method
    }))
    .on('error', err => {
        const msg = 'Error on connecting to the webservice.';
        console.error(msg, err);
        res.status(500).send(msg);
    })
    .pipe( res );
});

実際にキャッチされない例外が発生した場合は、アプリケーションを終了させるだけです。

2
Haroldo_OK