Skip to content

Commit 80c9ef0

Browse files
vieiraarturgjasnell
authored andcommitted
http: edit _storeHeader to check for Trailer header
Test non-chunked message does not have trailer header set, message will be terminated by the first empty line after the header fields, regardless of the header fields present in the message, and thus cannot contain a message body or 'trailers'. PR-URL: #12990 Ref: #2842 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Yuta Hiroto <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
1 parent 0ab4614 commit 80c9ef0

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

lib/_http_outgoing.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const checkInvalidHeaderChar = common._checkInvalidHeaderChar;
3333
const outHeadersKey = require('internal/http').outHeadersKey;
3434
const async_id_symbol = process.binding('async_wrap').async_id_symbol;
3535
const nextTick = require('internal/process/next_tick').nextTick;
36+
const errors = require('internal/errors');
3637

3738
const CRLF = common.CRLF;
3839
const debug = common.debug;
@@ -427,6 +428,14 @@ function _storeHeader(firstLine, headers) {
427428
}
428429
}
429430

431+
// Test non-chunked message does not have trailer header set,
432+
// message will be terminated by the first empty line after the
433+
// header fields, regardless of the header fields present in the
434+
// message, and thus cannot contain a message body or 'trailers'.
435+
if (this.chunkedEncoding !== true && state.trailer) {
436+
throw new errors.Error('ERR_HTTP_TRAILER_INVALID');
437+
}
438+
430439
this._header = state.header + CRLF;
431440
this._headerSent = false;
432441

lib/internal/errors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ E('ERR_PARSE_HISTORY_DATA',
155155
(oldHistoryPath) => `Could not parse history data in ${oldHistoryPath}`);
156156
E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed');
157157
E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed');
158+
E('ERR_HTTP_TRAILER_INVALID',
159+
'Trailers are invalid with this transfer encoding');
158160
E('ERR_UNKNOWN_BUILTIN_MODULE', (id) => `No such built-in module: ${id}`);
159161
E('ERR_UNKNOWN_SIGNAL', (signal) => `Unknown signal: ${signal}`);
160162
E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type');
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
// This test ensures that a Trailer header is set only when a chunked transfer
5+
// encoding is used.
6+
7+
const assert = require('assert');
8+
const http = require('http');
9+
10+
const server = http.createServer(common.mustCall(function(req, res) {
11+
res.setHeader('Trailer', 'baz');
12+
const trailerInvalidErr = {
13+
code: 'ERR_HTTP_TRAILER_INVALID',
14+
message: 'Trailers are invalid with this transfer encoding',
15+
type: Error
16+
};
17+
assert.throws(() => res.writeHead(200, {'Content-Length': '2'}),
18+
common.expectsError(trailerInvalidErr));
19+
res.removeHeader('Trailer');
20+
res.end('ok');
21+
}));
22+
server.listen(0, common.mustCall(() => {
23+
http.get({ port: server.address().port }, common.mustCall((res) => {
24+
assert.strictEqual(res.statusCode, 200);
25+
let buf = '';
26+
res.on('data', (chunk) => {
27+
buf += chunk;
28+
}).on('end', common.mustCall(() => {
29+
assert.strictEqual(buf, 'ok');
30+
}));
31+
server.close();
32+
}));
33+
}));

0 commit comments

Comments
 (0)