diff --git a/lib/server.js b/lib/server.js index 90b1883..6a89c02 100644 --- a/lib/server.js +++ b/lib/server.js @@ -66,7 +66,8 @@ function Server (options, origins) { // Remove the inline policy listener if we close down // but only when the server was `online` (see listen prototype) if (me.server['@'] && me.server.online) { - me.server.removeListener('connection', me.server['@']); + var event = this.server.cert ? 'secureConnection' : 'connection'; + me.server.removeListener(event, me.server['@']); } // not online anymore @@ -106,7 +107,7 @@ Server.prototype.listen = function listen (port, server, cb){ // no one in their right mind would ever create a `@` prototype, so Im just gonna store // my function on the server, so I can remove it later again once the server(s) closes this.server['@'] = function connection (socket) { - socket.once('data', function requestData (data) { + function requestData (data) { // if it's a Flash policy request, and we can write to the if ( data @@ -119,11 +120,30 @@ Server.prototype.listen = function listen (port, server, cb){ try { socket.end(me.buffer); } catch (e) {} } + } + + // Note: in some versions of node.js (tested with v0.12.7) the http.Server + // class closes the socket immediately when it sees that the request is not + // HTTP, before we manage to send the xml! So we need to make sure that our + // data listener is executed _first_. To do so we remove them all and + // we re-add them. + // In node v0.12.7 this trick was done for the connection event, in v4.2.1 + // this was broken for some reason, but doing it for the data event works. + // + var listeners = socket.listeners('data'); + socket.removeAllListeners('data'); + socket.once('data', requestData); + + listeners.forEach(function(l) { + socket.on('data', l); }); }; // attach it - this.server.on('connection', this.server['@']); + // support both https ('secureConnection' event) and http ('connection' event) + // + var event = this.server.cert ? 'secureConnection' : 'connection'; + this.server.on(event, this.server['@']); } // We add a callback method, so we can set a flag for when the server is `enabled` or `online`. @@ -250,7 +270,7 @@ Server.prototype.close = function close () { * Proxy the event listener requests to the created Net server */ -Object.keys(process.EventEmitter.prototype).forEach(function proxy (key){ +Object.keys(require('events').prototype).forEach(function proxy (key){ Server.prototype[key] = Server.prototype[key] || function () { if (this.socket) { this.socket[key].apply(this.socket, arguments); diff --git a/tests/unit.test.js b/tests/unit.test.js index 932b3c1..2d3c974 100644 --- a/tests/unit.test.js +++ b/tests/unit.test.js @@ -136,11 +136,20 @@ module.exports = { httpserver.listen(port, function(){ server.listen(port + 1, httpserver, function(){ var client = net.createConnection(port); + var gotData = false; client.write('\0'); client.on('error', function(err){ assert.ok(!err, err) }); + client.on('end', function(){ + assert.ok(gotData, 'connection closed before sending data'); + + // clean up + server.close(); + httpserver.close(); + }); client.on('data', function(data){ + gotData = true; var response = data.toString(); console.log(response); @@ -149,10 +158,8 @@ module.exports = { response.indexOf('domain="*"').should.be.above(0); response.indexOf('domain="google.com"').should.equal(-1); - // clean up - client.destroy(); - server.close(); - httpserver.close(); + // cleanup done by the 'end' handler + client.end(); }); }); }); @@ -228,4 +235,4 @@ module.exports = { server.close(); }); } -}; \ No newline at end of file +};