http: cleanup setHeader()

Several fields on OutgoingMessage were set after instantiation. These
have been included in the constructor to prevent mutation of the object
map after instantiation.

"name" is now explicitly checked to be a string. Where before if a
non-string was passed the following cryptic error was thrown:

    _http_outgoing.js:334
      var key = name.toLowerCase();
                     ^
    TypeError: undefined is not a function

Signed-off-by: Trevor Norris <trev.norris@gmail.com>
This commit is contained in:
Trevor Norris 2014-09-29 12:32:42 -07:00
parent de312cfd7c
commit 979d0ca874
2 changed files with 25 additions and 10 deletions

View File

@ -82,9 +82,13 @@ function OutgoingMessage() {
this.finished = false; this.finished = false;
this._hangupClose = false; this._hangupClose = false;
this._headerSent = false;
this.socket = null; this.socket = null;
this.connection = null; this.connection = null;
this._header = null;
this._headers = null;
this._headerNames = {};
} }
util.inherits(OutgoingMessage, Stream); util.inherits(OutgoingMessage, Stream);
@ -323,23 +327,22 @@ function storeHeader(self, state, field, value) {
OutgoingMessage.prototype.setHeader = function(name, value) { OutgoingMessage.prototype.setHeader = function(name, value) {
if (arguments.length < 2) { if (typeof name !== 'string')
throw new Error('`name` and `value` are required for setHeader().'); throw new TypeError('"name" should be a string');
} if (value === undefined)
throw new Error('"name" and "value" are required for setHeader().');
if (this._header) { if (this._header)
throw new Error('Can\'t set headers after they are sent.'); throw new Error('Can\'t set headers after they are sent.');
}
if (this._headers === null)
this._headers = {};
var key = name.toLowerCase(); var key = name.toLowerCase();
this._headers = this._headers || {};
this._headerNames = this._headerNames || {};
this._headers[key] = value; this._headers[key] = value;
this._headerNames[key] = name; this._headerNames[key] = name;
if (automaticHeaders[key]) { if (automaticHeaders[key])
this._removedHeader[key] = false; this._removedHeader[key] = false;
}
}; };
@ -387,6 +390,7 @@ OutgoingMessage.prototype._renderHeaders = function() {
var headers = {}; var headers = {};
var keys = Object.keys(this._headers); var keys = Object.keys(this._headers);
for (var i = 0, l = keys.length; i < l; i++) { for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i]; var key = keys[i];
headers[this._headerNames[key]] = this._headers[key]; headers[this._headerNames[key]] = this._headers[key];

View File

@ -28,6 +28,17 @@ var http = require('http');
var s = http.createServer(function(req, res) { var s = http.createServer(function(req, res) {
res.setHeader('test', '1'); res.setHeader('test', '1');
// toLowerCase() is used on the name argument, so it must be a string.
var threw = false;
try {
res.setHeader(0xf00, 'bar');
} catch (e) {
assert.ok(e instanceof TypeError);
threw = true;
}
assert.ok(threw, 'Non-string names should throw');
res.writeHead(200, { Test: '2' }); res.writeHead(200, { Test: '2' });
res.end(); res.end();
}); });