diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index de977eb19c4cb5..2e64632a73fbf2 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -78,6 +78,7 @@ exports.OutgoingMessage = OutgoingMessage; OutgoingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); + if (!this.socket) { this.once('socket', function(socket) { socket.setTimeout(msecs); @@ -133,32 +134,36 @@ OutgoingMessage.prototype._writeRaw = function(data, encoding, callback) { return true; } - if (this.connection && - this.connection._httpMessage === this && - this.connection.writable && - !this.connection.destroyed) { + var connection = this.connection; + if (connection && + connection._httpMessage === this && + connection.writable && + !connection.destroyed) { // There might be pending data in the this.output buffer. - while (this.output.length) { - if (!this.connection.writable) { - this._buffer(data, encoding, callback); - return false; + var outputLength = this.output.length; + if (outputLength > 0) { + var output = this.output; + var outputEncodings = this.outputEncodings; + var outputCallbacks = this.outputCallbacks; + for (var i = 0; i < outputLength; i++) { + connection.write(output[i], outputEncodings[i], + outputCallbacks[i]); } - var c = this.output.shift(); - var e = this.outputEncodings.shift(); - var cb = this.outputCallbacks.shift(); - this.connection.write(c, e, cb); + + this.output = []; + this.outputEncodings = []; + this.outputCallbacks = []; } // Directly write to socket. - return this.connection.write(data, encoding, callback); - } else if (this.connection && this.connection.destroyed) { + return connection.write(data, encoding, callback); + } else if (connection && connection.destroyed) { // The socket was destroyed. If we're still trying to write to it, // then we haven't gotten the 'close' event yet. return false; } else { // buffer, as long as we're not destroyed. - this._buffer(data, encoding, callback); - return false; + return this._buffer(data, encoding, callback); } }; @@ -183,8 +188,6 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) { messageHeader: firstLine }; - var field, value; - if (headers) { var keys = Object.keys(headers); var isArray = Array.isArray(headers); @@ -365,14 +368,16 @@ OutgoingMessage.prototype._renderHeaders = function() { throw new Error('Can\'t render headers after they are sent to the client.'); } - if (!this._headers) return {}; + var headersMap = this._headers; + if (!headersMap) return {}; var headers = {}; - var keys = Object.keys(this._headers); + var keys = Object.keys(headersMap); + var headerNames = this._headerNames; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; - headers[this._headerNames[key]] = this._headers[key]; + headers[headerNames[key]] = headersMap[key]; } return headers; }; @@ -571,13 +576,24 @@ OutgoingMessage.prototype._finish = function() { // This function, outgoingFlush(), is called by both the Server and Client // to attempt to flush any pending messages out to the socket. OutgoingMessage.prototype._flush = function() { - if (this.socket && this.socket.writable) { - var ret; - while (this.output.length) { - var data = this.output.shift(); - var encoding = this.outputEncodings.shift(); - var cb = this.outputCallbacks.shift(); - ret = this.socket.write(data, encoding, cb); + var socket = this.socket; + var outputLength, ret; + + if (socket && socket.writable) { + // There might be remaining data in this.output; write it out + outputLength = this.output.length; + if (outputLength > 0) { + var output = this.output; + var outputEncodings = this.outputEncodings; + var outputCallbacks = this.outputCallbacks; + for (var i = 0; i < outputLength; i++) { + ret = socket.write(output[i], outputEncodings[i], + outputCallbacks[i]); + } + + this.output = []; + this.outputEncodings = []; + this.outputCallbacks = []; } if (this.finished) {