Skip to content
Permalink
Browse files

http: improve parser error messages

Include the library-provided reason in the Error’s `message`.

Fixes: #28468

PR-URL: #28487
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
  • Loading branch information...
addaleax authored and targos committed Jun 30, 2019
1 parent 0777e09 commit 38f8cd5ba100a3922d84ae5bc6c3828559bbc693
@@ -33,6 +33,7 @@ const {
httpSocketSetup,
parsers,
HTTPParser,
prepareError,
} = require('_http_common');
const { OutgoingMessage } = require('_http_outgoing');
const Agent = require('_http_agent');
@@ -451,6 +452,7 @@ function socketOnData(d) {

const ret = parser.execute(d);
if (ret instanceof Error) {
prepareError(ret, parser, d);
debug('parse error', ret);
freeParser(parser, req, socket);
socket.destroy();
@@ -239,6 +239,12 @@ function cleanParser(parser) {
parser._consumed = false;
}

function prepareError(err, parser, rawPacket) {
err.rawPacket = rawPacket || parser.getCurrentBuffer();
if (typeof err.reason === 'string')
err.message = `Parse Error: ${err.reason}`;
}

module.exports = {
_checkInvalidHeaderChar: checkInvalidHeaderChar,
_checkIsHttpToken: checkIsHttpToken,
@@ -251,5 +257,6 @@ module.exports = {
methods,
parsers,
kIncomingMessage,
HTTPParser
HTTPParser,
prepareError,
};
@@ -35,7 +35,8 @@ const {
httpSocketSetup,
kIncomingMessage,
HTTPParser,
_checkInvalidHeaderChar: checkInvalidHeaderChar
_checkInvalidHeaderChar: checkInvalidHeaderChar,
prepareError,
} = require('_http_common');
const { OutgoingMessage } = require('_http_outgoing');
const { outHeadersKey, ondrain, nowDate } = require('internal/http');
@@ -553,6 +554,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
resetSocketTimeout(server, socket, state);

if (ret instanceof Error) {
prepareError(ret, parser, d);
ret.rawPacket = d || parser.getCurrentBuffer();
debug('parse error', ret);
socketOnError.call(socket, ret);
@@ -0,0 +1,32 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const http = require('http');
const net = require('net');

const response = Buffer.from('HTTP/1.1 200 OK\r\n' +
'Content-Length: 6\r\n' +
'Transfer-Encoding: Chunked\r\n' +
'\r\n' +
'6\r\nfoobar' +
'0\r\n');

const server = net.createServer(common.mustCall((conn) => {
conn.write(response);
}));

server.listen(0, common.mustCall(() => {
const req = http.get(`http://localhost:${server.address().port}/`);
req.end();
req.on('error', common.mustCall((err) => {
const reason = 'Content-Length can\'t be present with chunked encoding';
assert.strictEqual(err.message, `Parse Error: ${reason}`);
assert(err.bytesParsed < response.length);
assert(err.bytesParsed >= response.indexOf('Transfer-Encoding'));
assert.strictEqual(err.code, 'HPE_UNEXPECTED_CONTENT_LENGTH');
assert.strictEqual(err.reason, reason);
assert.deepStrictEqual(err.rawPacket, response);

server.close();
}));
}));
@@ -44,7 +44,7 @@ server.listen(0, common.mustCall(() => {
}).on('error', common.mustCall((e) => {
common.expectsError({
code: 'HPE_INVALID_CONSTANT',
message: 'Parse Error'
message: 'Parse Error: Expected HTTP/'
})(e);
countdown.dec();
}));
@@ -19,7 +19,7 @@ const server = createServer();
server.on('connection', mustCall((socket) => {
socket.on('error', expectsError({
type: Error,
message: 'Parse Error',
message: 'Parse Error: Header overflow',
code: 'HPE_HEADER_OVERFLOW',
bytesParsed: maxHeaderSize + PAYLOAD_GET.length,
rawPacket: Buffer.from(PAYLOAD)
@@ -13,7 +13,7 @@ server.on('clientError', common.mustCall(function(err, socket) {
assert.strictEqual(err instanceof Error, true);
assert.strictEqual(err.code, 'HPE_INVALID_METHOD');
assert.strictEqual(err.bytesParsed, 1);
assert.strictEqual(err.message, 'Parse Error');
assert.strictEqual(err.message, 'Parse Error: Invalid method encountered');
assert.strictEqual(err.rawPacket.toString(), 'Oopsie-doopsie\r\n');

socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
@@ -14,7 +14,7 @@ const server = createServer();
server.on('connection', mustCall((socket) => {
socket.on('error', expectsError({
type: Error,
message: 'Parse Error',
message: 'Parse Error: Invalid method encountered',
code: 'HPE_INVALID_METHOD',
bytesParsed: 0,
rawPacket: Buffer.from('FOO /\r\n')

0 comments on commit 38f8cd5

Please sign in to comment.
You can’t perform that action at this time.