Skip to content

Commit

Permalink
http: improve errors thrown in header validation
Browse files Browse the repository at this point in the history
PR-URL: #16719
Fixes: #16714
Reviewed-By: Anatoli Papirovski <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
joyeecheung committed Nov 6, 2017
1 parent 11a9f36 commit 0a84e95
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 26 deletions.
5 changes: 5 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,11 @@ more headers.
Used when an invalid character is found in an HTTP response status message
(reason phrase).

<a id="ERR_HTTP_INVALID_HEADER_VALUE"></a>
### ERR_HTTP_INVALID_HEADER_VALUE

Used to indicate that an invalid HTTP header value has been specified.

<a id="ERR_HTTP_INVALID_STATUS_CODE"></a>
### ERR_HTTP_INVALID_STATUS_CODE

Expand Down
38 changes: 18 additions & 20 deletions lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,16 +437,7 @@ function _storeHeader(firstLine, headers) {

function storeHeader(self, state, key, value, validate) {
if (validate) {
if (typeof key !== 'string' || !key || !checkIsHttpToken(key)) {
throw new errors.TypeError(
'ERR_INVALID_HTTP_TOKEN', 'Header name', key);
}
if (value === undefined) {
throw new errors.TypeError('ERR_MISSING_ARGS', `header "${key}"`);
} else if (checkInvalidHeaderChar(value)) {
debug('Header "%s" contains invalid characters', key);
throw new errors.TypeError('ERR_INVALID_CHAR', 'header content', key);
}
validateHeader(key, value);
}
state.header += key + ': ' + escapeHeaderValue(value) + CRLF;
matchHeader(self, state, key, value);
Expand Down Expand Up @@ -494,20 +485,27 @@ function matchHeader(self, state, field, value) {
}
}

function validateHeader(msg, name, value) {
if (typeof name !== 'string' || !name || !checkIsHttpToken(name))
throw new errors.TypeError('ERR_INVALID_HTTP_TOKEN', 'Header name', name);
if (value === undefined)
throw new errors.TypeError('ERR_MISSING_ARGS', 'value');
if (msg._header)
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'set');
if (checkInvalidHeaderChar(value)) {
function validateHeader(name, value) {
let err;
if (typeof name !== 'string' || !name || !checkIsHttpToken(name)) {
err = new errors.TypeError('ERR_INVALID_HTTP_TOKEN', 'Header name', name);
} else if (value === undefined) {
err = new errors.TypeError('ERR_HTTP_INVALID_HEADER_VALUE', value, name);
} else if (checkInvalidHeaderChar(value)) {
debug('Header "%s" contains invalid characters', name);
throw new errors.TypeError('ERR_INVALID_CHAR', 'header content', name);
err = new errors.TypeError('ERR_INVALID_CHAR', 'header content', name);
}
if (err !== undefined) {
Error.captureStackTrace(err, validateHeader);
throw err;
}
}

OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
validateHeader(this, name, value);
if (this._header) {
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'set');
}
validateHeader(name, value);

if (!this[outHeadersKey])
this[outHeadersKey] = {};
Expand Down
1 change: 1 addition & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ E('ERR_HTTP2_UNSUPPORTED_PROTOCOL',
E('ERR_HTTP_HEADERS_SENT',
'Cannot %s headers after they are sent to the client');
E('ERR_HTTP_INVALID_CHAR', 'Invalid character in statusMessage.');
E('ERR_HTTP_INVALID_HEADER_VALUE', 'Invalid value "%s" for header "%s"');
E('ERR_HTTP_INVALID_STATUS_CODE',
(originalStatusCode) => `Invalid status code: ${originalStatusCode}`);
E('ERR_HTTP_TRAILER_INVALID',
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-http-mutable-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ const s = http.createServer(common.mustCall((req, res) => {
common.expectsError(
() => res.setHeader('someHeader'),
{
code: 'ERR_MISSING_ARGS',
code: 'ERR_HTTP_INVALID_HEADER_VALUE',
type: TypeError,
message: 'The "value" argument must be specified'
message: 'Invalid value "undefined" for header "someHeader"'
}
);
common.expectsError(
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-http-outgoing-proto.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ assert.throws(() => {
const outgoingMessage = new OutgoingMessage();
outgoingMessage.setHeader('test');
}, common.expectsError({
code: 'ERR_MISSING_ARGS',
code: 'ERR_HTTP_INVALID_HEADER_VALUE',
type: TypeError,
message: 'The "value" argument must be specified'
message: 'Invalid value "undefined" for header "test"'
}));

assert.throws(() => {
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-http-write-head.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ const s = http.createServer(common.mustCall((req, res) => {
common.expectsError(
() => res.setHeader('foo', undefined),
{
code: 'ERR_MISSING_ARGS',
code: 'ERR_HTTP_INVALID_HEADER_VALUE',
type: TypeError,
message: 'The "value" argument must be specified'
message: 'Invalid value "undefined" for header "foo"'
}
);

Expand Down

0 comments on commit 0a84e95

Please sign in to comment.