Browse Source

Backport client 'upgrade' events

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
d89454e5d4
  1. 62
      lib/http.js
  2. 3
      test/simple/test-http-upgrade-client2.js

62
lib/http.js

@ -937,6 +937,12 @@ Agent.prototype.appendMessage = function(options) {
}; };
Agent.prototype._removeSocket = function(socket) {
var i = this.sockets.indexOf(socket);
if (i >= 0) this.sockets.splice(i, 1);
}
Agent.prototype._establishNewConnection = function() { Agent.prototype._establishNewConnection = function() {
var self = this; var self = this;
assert(this.sockets.length < this.maxSockets); assert(this.sockets.length < this.maxSockets);
@ -944,6 +950,7 @@ Agent.prototype._establishNewConnection = function() {
// Grab a new "socket". Depending on the implementation of _getConnection // Grab a new "socket". Depending on the implementation of _getConnection
// this could either be a raw TCP socket or a TLS stream. // this could either be a raw TCP socket or a TLS stream.
var socket = this._getConnection(this.host, this.port, function () { var socket = this._getConnection(this.host, this.port, function () {
self.emit('connect'); // mostly for the shim.
debug("Agent _getConnection callback"); debug("Agent _getConnection callback");
self._cycle(); self._cycle();
}); });
@ -985,8 +992,18 @@ Agent.prototype._establishNewConnection = function() {
// in the upgradeHead from the closing lines of the headers // in the upgradeHead from the closing lines of the headers
var upgradeHead = d.slice(start + bytesParsed + 1, end); var upgradeHead = d.slice(start + bytesParsed + 1, end);
// Make sure we don't try to send HTTP requests to it.
self._removeSocket(socket);
socket.on('end', function() {
self.emit('end');
});
// XXX free the parser?
if (self.listeners('upgrade').length) { if (self.listeners('upgrade').length) {
self.emit('upgrade', res, res.socket, upgradeHead); // Emit 'upgrade' on the Agent.
self.emit('upgrade', res, socket, upgradeHead);
} else { } else {
// Got upgrade header, but have no handler. // Got upgrade header, but have no handler.
socket.destroy(); socket.destroy();
@ -995,14 +1012,14 @@ Agent.prototype._establishNewConnection = function() {
}; };
socket.onend = function() { socket.onend = function() {
self.emit('end'); // mostly for the shim.
parser.finish(); parser.finish();
socket.destroy(); socket.destroy();
}; };
// When the socket closes remove it from the list of available sockets. // When the socket closes remove it from the list of available sockets.
socket.on('close', function() { socket.on('close', function() {
var i = self.sockets.indexOf(socket); self._removeSocket(socket);
if (i >= 0) self.sockets.splice(i, 1);
// unref the parser for easy gc // unref the parser for easy gc
parsers.free(parser); parsers.free(parser);
}); });
@ -1133,12 +1150,51 @@ exports.get = function(options, cb) {
// Shims to old interface. // Shims to old interface.
function Client(port, host) { function Client(port, host) {
var self = this;
this.port = port; this.port = port;
this.host = host; this.host = host;
this.agent = getAgent(this.host, this.port);
// proxy connect events upwards;
this.agent.on('connect', function() {
self.emit('connect');
});
this.agent.on('end', function() {
self.emit('end');
});
// proxy upgrade events upwards;
this.agent.on('upgrade', function (res, socket, upgradeHead) {
if (self.listeners('upgrade').length) {
self.emit('upgrade', res, socket, upgradeHead);
} else {
socket.destroy();
}
});
} }
util.inherits(Client, EventEmitter); util.inherits(Client, EventEmitter);
// This method is used in a few tests to force the connections closed.
// Again - just a shim so as not to break code. Not really important.
Client.prototype.end = function() {
for (var i = 0; i < this.agent.sockets.length; i++) {
var socket = this.agent.sockets[i];
if (!socket._httpMessage && socket.writable) socket.end();
}
};
Client.prototype.destroy = function(e) {
for (var i = 0; i < this.agent.sockets.length; i++) {
var socket = this.agent.sockets[i];
socket.destroy(e);
}
};
Client.prototype.request = function(method, path, headers) { Client.prototype.request = function(method, path, headers) {
if (typeof(path) != 'string') { if (typeof(path) != 'string') {
// assume method was omitted, shift arguments // assume method was omitted, shift arguments

3
test/simple/test-http-upgrade-client2.js

@ -21,11 +21,13 @@ server.listen(common.PORT, function() {
var client = http.createClient(common.PORT); var client = http.createClient(common.PORT);
function upgradeRequest(fn) { function upgradeRequest(fn) {
console.log("req");
var header = { 'Connection': 'Upgrade', 'Upgrade': 'Test' }; var header = { 'Connection': 'Upgrade', 'Upgrade': 'Test' };
var request = client.request('GET', '/', header); var request = client.request('GET', '/', header);
var wasUpgrade = false; var wasUpgrade = false;
function onUpgrade(res, socket, head) { function onUpgrade(res, socket, head) {
console.log("client upgraded");
wasUpgrade = true; wasUpgrade = true;
client.removeListener('upgrade', onUpgrade); client.removeListener('upgrade', onUpgrade);
@ -34,6 +36,7 @@ server.listen(common.PORT, function() {
client.on('upgrade', onUpgrade); client.on('upgrade', onUpgrade);
function onEnd() { function onEnd() {
console.log("client end");
client.removeListener('end', onEnd); client.removeListener('end', onEnd);
if (!wasUpgrade) { if (!wasUpgrade) {
throw new Error('hasn\'t received upgrade event'); throw new Error('hasn\'t received upgrade event');

Loading…
Cancel
Save