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();
|
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() {
|
function socketOnEnd() {
|
||||||
var socket = this;
|
var socket = this;
|
||||||
var req = this._httpMessage;
|
var req = this._httpMessage;
|
||||||
@ -448,6 +455,7 @@ function responseOnEnd() {
|
|||||||
}
|
}
|
||||||
socket.removeListener('close', socketCloseListener);
|
socket.removeListener('close', socketCloseListener);
|
||||||
socket.removeListener('error', socketErrorListener);
|
socket.removeListener('error', socketErrorListener);
|
||||||
|
socket.once('error', freeSocketErrorListener);
|
||||||
// Mark this socket as available, AFTER user-added end
|
// Mark this socket as available, AFTER user-added end
|
||||||
// handlers have a chance to run.
|
// handlers have a chance to run.
|
||||||
process.nextTick(emitFreeNT, socket);
|
process.nextTick(emitFreeNT, socket);
|
||||||
@ -483,6 +491,7 @@ function tickOnSocket(req, socket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parser.onIncoming = parserOnIncomingClient;
|
parser.onIncoming = parserOnIncomingClient;
|
||||||
|
socket.removeListener('error', freeSocketErrorListener);
|
||||||
socket.on('error', socketErrorListener);
|
socket.on('error', socketErrorListener);
|
||||||
socket.on('data', socketOnData);
|
socket.on('data', socketOnData);
|
||||||
socket.on('end', socketOnEnd);
|
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