Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
91b8c5b
src: remove function hasTextDecoder in encoding.js
chichiwang Oct 12, 2018
acd7312
crypto: reduce memory usage of SignFinal
tniessen Oct 11, 2018
22ee1e3
zlib: do not leak on destroy
mafintosh Oct 18, 2018
c00a830
src: memory management using smart pointer
uttampawar Oct 12, 2018
e8200c0
src: simplify `TimerFunctionCall()` in `node_perf.cc`
addaleax Oct 20, 2018
93d4163
tls: throw if protocol too long
Oct 12, 2018
50b22de
doc, test: document and test vm timeout escapes
jasnell Oct 18, 2018
83888e8
test: mark test-vm-timeout-* known issue tests flaky
jasnell Oct 24, 2018
9df556c
build: expose more openssl categories for addons
JCMais Oct 9, 2018
784f1a0
src: avoid extra `Persistent` in `DefaultTriggerAsyncIdScope`
addaleax Oct 24, 2018
1156606
src: cache the result of GetOptions() in JS land
joyeecheung Nov 4, 2018
2ff9143
build: only try to find node when it's needed by the target
joyeecheung Nov 6, 2018
c85c2ce
test: http-client-timeout error assert arguments
rangle-tadhg Nov 6, 2018
a4620ab
test: fix arguments order
franher Nov 6, 2018
abf575d
child_process: allow 'http_parser' monkey patching again
Jimbly Oct 31, 2018
4ca0134
test: fs readfile, swap arguments in strictEqual
dodev Nov 6, 2018
9dbe096
test: swap the order of arguments
mhamwala Nov 6, 2018
71a61dd
test: strictEqual argument order (actual, expected)
ahmadnassri Nov 6, 2018
c769b8b
test: fix invalid argument order in test-http-expect-continue.js
mroderick Nov 6, 2018
7574f3f
test: change order of assert.strictEqual()
remypar5 Nov 6, 2018
27cb911
test: fix assert parameter order
Nov 6, 2018
e06bb47
test: swap expected and actual in assert.strictEqual
Nov 6, 2018
84a9ba4
test: add tests for OutgoingMessage setTimeout
robin-drexler Nov 6, 2018
d175a2e
test: fixing arguments order in `assert.strictEqual()`
gcarcaci Nov 6, 2018
d9489e1
test: fixe argument order in assert.strictEqual
posth Nov 6, 2018
1d88f01
test: fix arguments order
simonaco Nov 6, 2018
88231ca
test: switch arguments in strictEqual
mthpvg Nov 6, 2018
a7f604a
test: fix argument order in assert.strictEqual()
Nov 6, 2018
30d9588
test: fix arguments order in test-fs-write-buffer
razvanbh Nov 6, 2018
040ed21
test: removed extraneous argument 's'
jacksonchui Nov 7, 2018
0e5fe9a
test: fix assert argument order
manishepoch Nov 6, 2018
561ac4c
test: fix arguments order in assert.strictEqual
Nov 6, 2018
ee821b4
test: fix order in assert.strictEqual to actual, expected
Nov 6, 2018
56edd9f
test: fix the arguments order in `assert.strictEqual`
michael-zucker Nov 7, 2018
52f3ecc
test: fix the arguments order in `assert.strictEqual`
michael-zucker Nov 7, 2018
042e379
doc: fix some inconsistent use of hostname
sam-github Nov 6, 2018
81ff70d
test: switch order of strictEqual arguments
jpolack Nov 6, 2018
b264d7e
test: change arguments order in strictEqual
Paul-Isache Nov 6, 2018
f657e40
buffer: fix writeUInt16BE range check
mscdex Nov 6, 2018
c2f7f26
test: fix order of arguments in test-delayed-require assertion
reineke-fox Nov 6, 2018
d6f6c62
test: add error code tests in dgram test
markarranz Nov 7, 2018
0056c08
url: make the context non-enumerable
joyeecheung Nov 7, 2018
8c59ebb
benchmark: support more options in startup benchmark
joyeecheung Nov 6, 2018
d35739d
doc: describe what tls servername is for
sam-github Nov 7, 2018
2de3376
src: reuse std::make_unique
alyssaq Nov 6, 2018
64f7622
test: fix NewFromUtf8 compiler warning
danbev Nov 7, 2018
bb871c9
test: add coverage for escape key switch case
Nov 6, 2018
f50beda
test: add test for 'ERR_INVALID_CALLBACK'
razvanbh Nov 7, 2018
802d4b8
doc: fix code examples in stream.md
grantcarthew Nov 5, 2018
5dec2ca
tracing: fix static destruction order issue
addaleax Nov 6, 2018
9f023c4
test: fix order of arguments in assert.strictEqual
eiskalteschatten Nov 6, 2018
36861ad
test: add coverage for systemerror set name
amer8 Nov 6, 2018
899245f
test: add test for strictDeepEqual
nikita-malyschkin Nov 7, 2018
8209ecd
test: use assert.strictEqual instead of assert.equal
prog1dev Oct 15, 2018
a3289bd
test: fix uses of deprecated assert.fail with multiple args
prog1dev Oct 15, 2018
c0dad7a
doc: edit BUILDING.md
Trott Nov 8, 2018
ae2f959
test: move test-fs-watch-system-limit from sequential to pummel
mmmscott Oct 16, 2018
ee09fe3
lib: combine contructor, tag, Object into a function
Paul-Isache Nov 6, 2018
8e7f075
build,tools: update make-v8.sh for s390x
refack Oct 23, 2018
7d2bcf9
test: use NULL instead of 0 in common.h
danbev Nov 5, 2018
08c9e2b
net: simplify Socket.prototype._final
addaleax Nov 4, 2018
e9ca5bf
test: increase coverage internal readline
cyanic-webdesign Nov 6, 2018
db709c5
net: partially revert "simplify Socket.prototype._final"
addaleax Nov 10, 2018
f41eddc
stream: make `.destroy()` interact better with write queue
addaleax Nov 3, 2018
7ba4b9f
test: replacing fixture directory with temp
saurabhSiddhu Nov 4, 2018
043c70a
build: lint commit message in separate Travis job
richardlau Nov 8, 2018
c777ce7
test : compare objects not identical by reference
meelie Nov 6, 2018
07c6db9
test: fix assert.strictEqual argument order
mcqj Nov 6, 2018
3f7d7da
test: fix arguments order in assert.strictEqual()
ulisesantana Nov 6, 2018
e6ae331
doc: add oyyd to collaborators
oyyd Nov 11, 2018
808355e
test: add test for deepEqual Float32Array
yehiyam Nov 6, 2018
b23b6a4
test: add test case for completion bash flag
Nov 6, 2018
0d65b4b
doc: correct async_hooks sample outputs
Flarna Nov 2, 2018
7483c5b
test: correct order of args in assert.strictEqual()
Nov 6, 2018
a4037bc
doc: add links to Stream section
dmitigr Nov 11, 2018
d52709f
console: cover .assert with single argument
mroderick Nov 6, 2018
6805908
doc: update fs.open() changes record for optional 'flags'
rvagg Nov 8, 2018
77c2cc9
test: fix strictEqual argument order
Nov 6, 2018
13fead6
test: fix expectation in test-bootstrap-modules
ofrobots Dec 18, 2018
a5727ff
doc: sort bottom-of-file markdown links
sam-github Nov 27, 2018
57ccaf6
doc: correct async_hooks resource names
Flarna Nov 27, 2018
844bd62
deps: V8: cherry-pick 52a9e67
ofrobots Dec 14, 2018
c5140f5
http: fix regression of binary upgrade response body
mcollina Dec 14, 2018
5f649f6
test: move benchmark tests out of main test suite
Trott Nov 9, 2018
dc79fea
deps: cherry-pick http_parser_set_max_header_size
cjihrig Nov 29, 2018
82ad2c2
src: add kUInteger parsing
mcollina Dec 18, 2018
d21ff98
cli: add --max-http-header-size flag
cjihrig Dec 3, 2018
b7bb114
test: remove magic numbers in test-gc-http-client-onerror
Trott Dec 10, 2018
f30d169
doc: describe current HTTP header size limit
sam-github Nov 28, 2018
17f4208
http: add maxHeaderSize property
cjihrig Dec 6, 2018
47364b7
test: mark test-repl-envvars as flaky on AIX
MylesBorins Dec 26, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cli: add --max-http-header-size flag
Allow the maximum size of HTTP headers to be overridden from
the command line.

Backport-PR-URL: #25168
co-authored-by: Matteo Collina <hello@matteocollina.com>
PR-URL: #24811
Fixes: #24692
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
  • Loading branch information
2 people authored and MylesBorins committed Dec 22, 2018
commit d21ff98d832fc7a7d34ebcda23702fe9b5ea511b
8 changes: 8 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ added: v9.0.0

Specify the `file` of the custom [experimental ECMAScript Module][] loader.

### `--max-http-header-size=size`
<!-- YAML
added: REPLACEME
-->

Specify the maximum size, in bytes, of HTTP headers. Defaults to 8KB.

### `--napi-modules`
<!-- YAML
added: v7.10.0
Expand Down Expand Up @@ -584,6 +591,7 @@ Node.js options that are allowed are:
- `--inspect-brk`
- `--inspect-port`
- `--loader`
- `--max-http-header-size`
- `--napi-modules`
- `--no-deprecation`
- `--no-force-async-hooks-checks`
Expand Down
3 changes: 3 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ Specify the
as a custom loader, to load
.Fl -experimental-modules .
.
.It Fl -max-http-header-size Ns = Ns Ar size
Specify the maximum size of HTTP headers in bytes. Defaults to 8KB.
.
.It Fl -napi-modules
This option is a no-op.
It is kept for compatibility.
Expand Down
7 changes: 7 additions & 0 deletions src/node_http_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,10 @@ const struct http_parser_settings Parser::settings = {
nullptr // on_chunk_complete
};

void InitMaxHttpHeaderSizeOnce() {
const uint32_t max_http_header_size = per_process_opts->max_http_header_size;
http_parser_set_max_header_size(max_http_header_size);
}

void Initialize(Local<Object> target,
Local<Value> unused,
Expand Down Expand Up @@ -784,6 +788,9 @@ void Initialize(Local<Object> target,

target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"),
t->GetFunction(env->context()).ToLocalChecked());

static uv_once_t init_once = UV_ONCE_INIT;
uv_once(&init_once, InitMaxHttpHeaderSizeOnce);
}

} // anonymous namespace
Expand Down
4 changes: 4 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ PerProcessOptionsParser::PerProcessOptionsParser() {
kAllowedInEnvironment);
AddAlias("--trace-events-enabled", {
"--trace-event-categories", "v8,node,node.async_hooks" });
AddOption("--max-http-header-size",
"set the maximum size of HTTP headers (default: 8KB)",
&PerProcessOptions::max_http_header_size,
kAllowedInEnvironment);
AddOption("--v8-pool-size",
"set V8's thread pool size",
&PerProcessOptions::v8_thread_pool_size,
Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class PerProcessOptions : public Options {
std::string title;
std::string trace_event_categories;
std::string trace_event_file_pattern = "node_trace.${rotation}.log";
uint64_t max_http_header_size = 8 * 1024;
int64_t v8_thread_pool_size = 4;
bool zero_fill_all_buffers = false;

Expand Down
71 changes: 47 additions & 24 deletions test/sequential/test-http-max-http-headers.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
// Flags: --expose-internals
'use strict';

const assert = require('assert');
const common = require('../common');
const http = require('http');
const net = require('net');
const MAX = 8 * 1024; // 8KB
const MAX = +(process.argv[2] || 8 * 1024); // Command line option, or 8KB.

const { getOptionValue } = require('internal/options');

console.log('pid is', process.pid);
console.log('max header size is', getOptionValue('--max-http-header-size'));

// Verify that we cannot receive more than 8KB of headers.

Expand All @@ -28,19 +34,15 @@ function fillHeaders(headers, currentSize, valid = false) {
headers += 'a'.repeat(MAX - headers.length - 3);
// Generate valid headers
if (valid) {
// TODO(mcollina): understand why -9 is needed instead of -1
headers = headers.slice(0, -9);
// TODO(mcollina): understand why -32 is needed instead of -1
headers = headers.slice(0, -32);
}
return headers + '\r\n\r\n';
}

const timeout = common.platformTimeout(10);

function writeHeaders(socket, headers) {
const array = [];

// this is off from 1024 so that \r\n does not get split
const chunkSize = 1000;
const chunkSize = 100;
let last = 0;

for (let i = 0; i < headers.length / chunkSize; i++) {
Expand All @@ -55,19 +57,25 @@ function writeHeaders(socket, headers) {
next();

function next() {
if (socket.write(array.shift())) {
if (array.length === 0) {
socket.end();
} else {
setTimeout(next, timeout);
}
if (socket.destroyed) {
console.log('socket was destroyed early, data left to write:',
array.join('').length);
return;
}

const chunk = array.shift();

if (chunk) {
console.log('writing chunk of size', chunk.length);
socket.write(chunk, next);
} else {
socket.once('drain', next);
socket.end();
}
}
}

function test1() {
console.log('test1');
let headers =
'HTTP/1.1 200 OK\r\n' +
'Content-Length: 0\r\n' +
Expand All @@ -82,6 +90,9 @@ function test1() {
writeHeaders(sock, headers);
sock.resume();
});

// The socket might error but that's ok
sock.on('error', () => {});
});

server.listen(0, common.mustCall(() => {
Expand All @@ -90,17 +101,17 @@ function test1() {

client.on('error', common.mustCall((err) => {
assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW');
server.close();
setImmediate(test2);
server.close(test2);
}));
}));
}

const test2 = common.mustCall(() => {
console.log('test2');
let headers =
'GET / HTTP/1.1\r\n' +
'Host: localhost\r\n' +
'Agent: node\r\n' +
'Agent: nod2\r\n' +
'X-CRASH: ';

// /, Host, localhost, Agent, node, X-CRASH, a...
Expand All @@ -109,7 +120,7 @@ const test2 = common.mustCall(() => {

const server = http.createServer(common.mustNotCall());

server.on('clientError', common.mustCall((err) => {
server.once('clientError', common.mustCall((err) => {
assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW');
}));

Expand All @@ -121,34 +132,46 @@ const test2 = common.mustCall(() => {
});

finished(client, common.mustCall((err) => {
server.close();
setImmediate(test3);
server.close(test3);
}));
}));
});

const test3 = common.mustCall(() => {
console.log('test3');
let headers =
'GET / HTTP/1.1\r\n' +
'Host: localhost\r\n' +
'Agent: node\r\n' +
'Agent: nod3\r\n' +
'X-CRASH: ';

// /, Host, localhost, Agent, node, X-CRASH, a...
const currentSize = 1 + 4 + 9 + 5 + 4 + 7;
headers = fillHeaders(headers, currentSize, true);

console.log('writing', headers.length);

const server = http.createServer(common.mustCall((req, res) => {
res.end('hello world');
setImmediate(server.close.bind(server));
res.end('hello from test3 server');
server.close();
}));

server.on('clientError', (err) => {
console.log(err.code);
if (err.code === 'HPE_HEADER_OVERFLOW') {
console.log(err.rawPacket.toString('hex'));
}
});
server.on('clientError', common.mustNotCall());

server.listen(0, common.mustCall(() => {
const client = net.connect(server.address().port);
client.on('connect', () => {
writeHeaders(client, headers);
client.resume();
});

client.pipe(process.stdout);
}));
});

Expand Down
104 changes: 104 additions & 0 deletions test/sequential/test-set-http-max-http-headers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const { spawn } = require('child_process');
const path = require('path');
const testName = path.join(__dirname, 'test-http-max-http-headers.js');

const timeout = common.platformTimeout(100);

const tests = [];

function test(fn) {
tests.push(fn);
}

test(function(cb) {
console.log('running subtest expecting failure');

// Validate that the test fails if the max header size is too small.
const args = ['--expose-internals',
'--max-http-header-size=1024',
testName];
const cp = spawn(process.execPath, args, { stdio: 'inherit' });

cp.on('close', common.mustCall((code, signal) => {
assert.strictEqual(code, 1);
assert.strictEqual(signal, null);
cb();
}));
});

test(function(cb) {
console.log('running subtest expecting success');

const env = Object.assign({}, process.env, {
NODE_DEBUG: 'http'
});

// Validate that the test fails if the max header size is too small.
// Validate that the test now passes if the same limit becomes large enough.
const args = ['--expose-internals',
'--max-http-header-size=1024',
testName,
'1024'];
const cp = spawn(process.execPath, args, {
env,
stdio: 'inherit'
});

cp.on('close', common.mustCall((code, signal) => {
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
cb();
}));
});

// Next, repeat the same checks using NODE_OPTIONS if it is supported.
if (process.config.variables.node_without_node_options) {
const env = Object.assign({}, process.env, {
NODE_OPTIONS: '--max-http-header-size=1024'
});

test(function(cb) {
console.log('running subtest expecting failure');

// Validate that the test fails if the max header size is too small.
const args = ['--expose-internals', testName];
const cp = spawn(process.execPath, args, { env, stdio: 'inherit' });

cp.on('close', common.mustCall((code, signal) => {
assert.strictEqual(code, 1);
assert.strictEqual(signal, null);
cb();
}));
});

test(function(cb) {
// Validate that the test now passes if the same limit
// becomes large enough.
const args = ['--expose-internals', testName, '1024'];
const cp = spawn(process.execPath, args, { env, stdio: 'inherit' });

cp.on('close', common.mustCall((code, signal) => {
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
cb();
}));
});
}

function runTest() {
const fn = tests.shift();

if (!fn) {
return;
}

fn(() => {
setTimeout(runTest, timeout);
});
}

runTest();