http: handle errors on idle sockets
This change adds a new event handler to the `error` event of the socket after it has been used by the http_client. The purpose of this change is to catch errors on *keep alived* connections from idle sockets that otherwise will cause an uncaugh error event on the application. Fix: #3595 PR-URL: https://github.com/nodejs/node/pull/4482 Reviewed-By: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
parent
68bafb8baf
commit
5a2541de81
@ -282,6 +282,13 @@ function socketErrorListener(err) {
|
||||
socket.destroy();
|
||||
}
|
||||
|
||||
function freeSocketErrorListener(err) {
|
||||
var socket = this;
|
||||
debug('SOCKET ERROR on FREE socket:', err.message, err.stack);
|
||||
socket.destroy();
|
||||
socket.emit('agentRemove');
|
||||
}
|
||||
|
||||
function socketOnEnd() {
|
||||
var socket = this;
|
||||
var req = this._httpMessage;
|
||||
@ -448,6 +455,7 @@ function responseOnEnd() {
|
||||
}
|
||||
socket.removeListener('close', socketCloseListener);
|
||||
socket.removeListener('error', socketErrorListener);
|
||||
socket.once('error', freeSocketErrorListener);
|
||||
// Mark this socket as available, AFTER user-added end
|
||||
// handlers have a chance to run.
|
||||
process.nextTick(emitFreeNT, socket);
|
||||
@ -483,6 +491,7 @@ function tickOnSocket(req, socket) {
|
||||
}
|
||||
|
||||
parser.onIncoming = parserOnIncomingClient;
|
||||
socket.removeListener('error', freeSocketErrorListener);
|
||||
socket.on('error', socketErrorListener);
|
||||
socket.on('data', socketOnData);
|
||||
socket.on('end', socketOnEnd);
|
||||
|
56
test/parallel/test-http-agent-error-on-idle.js
Normal file
56
test/parallel/test-http-agent-error-on-idle.js
Normal file
@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var Agent = http.Agent;
|
||||
|
||||
var agent = new Agent({
|
||||
keepAlive: true,
|
||||
});
|
||||
|
||||
var requestParams = {
|
||||
host: 'localhost',
|
||||
port: common.PORT,
|
||||
agent: agent,
|
||||
path: '/'
|
||||
};
|
||||
|
||||
var socketKey = agent.getName(requestParams);
|
||||
|
||||
function get(callback) {
|
||||
return http.get(requestParams, callback);
|
||||
}
|
||||
|
||||
var destroy_queue = {};
|
||||
var server = http.createServer(function(req, res) {
|
||||
res.end('hello world');
|
||||
});
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
get(function(res) {
|
||||
assert.equal(res.statusCode, 200);
|
||||
res.resume();
|
||||
res.on('end', function() {
|
||||
process.nextTick(function() {
|
||||
var freeSockets = agent.freeSockets[socketKey];
|
||||
assert.equal(freeSockets.length, 1,
|
||||
'expect a free socket on ' + socketKey);
|
||||
|
||||
//generate a random error on the free socket
|
||||
var freeSocket = freeSockets[0];
|
||||
freeSocket.emit('error', new Error('ECONNRESET: test'));
|
||||
|
||||
get(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function done() {
|
||||
assert.equal(Object.keys(agent.freeSockets).length, 0,
|
||||
'expect the freeSockets pool to be empty');
|
||||
|
||||
agent.destroy();
|
||||
server.close();
|
||||
process.exit(0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user