From ec576235f1f4d7f5873cf3c0118b28c022740ffe Mon Sep 17 00:00:00 2001 From: isaacs Date: Wed, 8 May 2013 14:28:56 -0700 Subject: [PATCH] http: Use writev instead of the hacky hot end --- lib/_http_outgoing.js | 116 ++++++------------------------------------ 1 file changed, 16 insertions(+), 100 deletions(-) diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 57394b408b9..7248e5a1350 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -460,6 +460,10 @@ var crlf_buf = new Buffer('\r\n'); OutgoingMessage.prototype.end = function(data, encoding) { + if (data && typeof data !== 'string' && !Buffer.isBuffer(data)) { + throw new TypeError('first argument must be a string or Buffer'); + } + if (this.finished) { return false; } @@ -473,113 +477,25 @@ OutgoingMessage.prototype.end = function(data, encoding) { data = false; } + if (this.connection && data) + this.connection.cork(); + var ret; - - var hot = this._headerSent === false && - (data && data.length > 0) && - this.output.length === 0 && - this.connection && - this.connection.writable && - this.connection._httpMessage === this; - - // The benefits of the hot-path optimization below start to fall - // off when the buffer size gets up near 128KB, because the cost - // of the copy is more than the cost of the extra write() call. - // Switch to the write/end method at that point. Heuristics and - // magic numbers are awful, but slow http responses are worse. - if (hot && Buffer.isBuffer(data) && data.length > 120 * 1024) - hot = false; - - if (hot) { - // Hot path. They're doing - // res.writeHead(); - // res.end(blah); - // HACKY. - - if (typeof data === 'string') { - if (this.chunkedEncoding) { - var l = Buffer.byteLength(data, encoding).toString(16); - ret = this.connection.write(this._header + l + CRLF + - data + '\r\n0\r\n' + - this._trailer + '\r\n', encoding); - } else { - ret = this.connection.write(this._header + data, encoding); - } - } else if (Buffer.isBuffer(data)) { - if (this.chunkedEncoding) { - var chunk_size = data.length.toString(16); - - // Skip expensive Buffer.byteLength() calls; only ISO-8859-1 characters - // are allowed in HTTP headers. Therefore: - // - // this._header.length == Buffer.byteLength(this._header.length) - // this._trailer.length == Buffer.byteLength(this._trailer.length) - // - var header_len = this._header.length; - var chunk_size_len = chunk_size.length; - var data_len = data.length; - var trailer_len = this._trailer.length; - - var len = header_len + - chunk_size_len + - 2 + // '\r\n'.length - data_len + - 5 + // '\r\n0\r\n'.length - trailer_len + - 2; // '\r\n'.length - - var buf = new Buffer(len); - var off = 0; - - buf.write(this._header, off, header_len, 'ascii'); - off += header_len; - - buf.write(chunk_size, off, chunk_size_len, 'ascii'); - off += chunk_size_len; - - crlf_buf.copy(buf, off); - off += 2; - - data.copy(buf, off); - off += data_len; - - zero_chunk_buf.copy(buf, off); - off += 5; - - if (trailer_len > 0) { - buf.write(this._trailer, off, trailer_len, 'ascii'); - off += trailer_len; - } - - crlf_buf.copy(buf, off); - - ret = this.connection.write(buf); - } else { - var header_len = this._header.length; - var buf = new Buffer(header_len + data.length); - buf.write(this._header, 0, header_len, 'ascii'); - data.copy(buf, header_len); - ret = this.connection.write(buf); - } - } else { - throw new TypeError('first argument must be a string or Buffer'); - } - this._headerSent = true; - - } else if (data) { + if (data) { // Normal body write. ret = this.write(data, encoding); } - if (!hot) { - if (this.chunkedEncoding) { - ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk. - } else { - // Force a flush, HACK. - ret = this._send(''); - } + if (this.chunkedEncoding) { + ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk. + } else { + // Force a flush, HACK. + ret = this._send(''); } + if (this.connection && data) + this.connection.uncork(); + this.finished = true; // There is the first message on the outgoing queue, and we've sent