Skip to content

Commit 3956f4e

Browse files
committed
https: add maxHeaderSize option for https server
Fixes: nodejs#38954 Refs: nodejs#30570
1 parent 82b44f4 commit 3956f4e

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

doc/api/https.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ See [`http.Server#keepAliveTimeout`][].
158158
## `https.createServer([options][, requestListener])`
159159
<!-- YAML
160160
added: v0.3.4
161+
changes:
162+
- version: REPLACEME
163+
pr-url: REPLACEME
164+
description: Support `maxHeaderSize` option.
161165
-->
162166

163167
* `options` {Object} Accepts `options` from [`tls.createServer()`][],

lib/https.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ let debug = require('internal/util/debuglog').debuglog('https', (fn) => {
5050
const { URL, urlToHttpOptions, searchParamsSymbol } = require('internal/url');
5151
const { IncomingMessage, ServerResponse } = require('http');
5252
const { kIncomingMessage } = require('_http_common');
53+
const { validateInteger } = require('internal/validators');
5354

5455
function Server(opts, requestListener) {
5556
if (!(this instanceof Server)) return new Server(opts, requestListener);
@@ -67,6 +68,12 @@ function Server(opts, requestListener) {
6768
opts.ALPNProtocols = ['http/1.1'];
6869
}
6970

71+
this.maxHeaderSize = 0;
72+
if (opts.maxHeaderSize !== undefined) {
73+
validateInteger(opts.maxHeaderSize, 'maxHeaderSize', 0);
74+
this.maxHeaderSize = opts.maxHeaderSize;
75+
}
76+
7077
this[kIncomingMessage] = opts.IncomingMessage || IncomingMessage;
7178
this[kServerResponse] = opts.ServerResponse || ServerResponse;
7279

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
if (!common.hasCrypto) {
6+
common.skip('missing crypto');
7+
}
8+
9+
const assert = require('assert');
10+
const https = require('https');
11+
const fixtures = require('../common/fixtures');
12+
13+
14+
const options = {
15+
key: fixtures.readKey('agent1-key.pem'),
16+
cert: fixtures.readKey('agent1-cert.pem')
17+
};
18+
19+
const maxHeaderSize = 8192;
20+
21+
const body = 'hello world\n';
22+
const serverCallback = (req, res) => {
23+
res.writeHead(200, { 'content-type': 'text/plain' });
24+
res.end(body);
25+
};
26+
27+
const commonReqOptions = {
28+
hostname: '127.0.0.1',
29+
path: '/',
30+
method: 'GET',
31+
rejectUnauthorized: false,
32+
};
33+
34+
// Test when header size is larger than maxHeaderSize
35+
{
36+
const server = https.createServer({
37+
...options,
38+
maxHeaderSize
39+
}, serverCallback);
40+
41+
server.listen(0, common.mustCall(() => {
42+
const serverPort = server.address().port;
43+
const reqOptions = {
44+
...commonReqOptions,
45+
port: serverPort,
46+
headers: {
47+
'h': 'a'.repeat(maxHeaderSize + 1)
48+
}
49+
};
50+
51+
https
52+
.request(reqOptions, common.mustCall((res) => {
53+
assert.strictEqual(res.statusCode, 431);
54+
55+
res.on('data', () => {});
56+
57+
res.on('end', common.mustCall(() => {
58+
server.close();
59+
}));
60+
}))
61+
.end();
62+
}));
63+
}
64+
65+
// Test when header size is within the range
66+
{
67+
const server = https.createServer({
68+
...options,
69+
maxHeaderSize
70+
}, serverCallback);
71+
72+
server.listen(0, common.mustCall(() => {
73+
const serverPort = server.address().port;
74+
const reqOptions = {
75+
...commonReqOptions,
76+
port: serverPort,
77+
headers: {
78+
// Some other header overhead
79+
'h': 'a'.repeat(maxHeaderSize - 200)
80+
}
81+
};
82+
83+
https
84+
.request(reqOptions, common.mustCall((res) => {
85+
assert.strictEqual(res.statusCode, 200);
86+
87+
res.on('data', () => {});
88+
89+
res.on('end', common.mustCall(() => {
90+
server.close();
91+
}));
92+
}))
93+
.end();
94+
}));
95+
}
96+
97+
98+
// Test parameter validation
99+
{
100+
assert.throws(common.mustCall(() => {
101+
https.createServer({
102+
...options,
103+
maxHeaderSize: -1
104+
}, serverCallback);
105+
}), {
106+
message: 'The value of "maxHeaderSize" is out of range. ' +
107+
'It must be >= 0 && <= 9007199254740991. Received -1',
108+
code: 'ERR_OUT_OF_RANGE',
109+
name: 'RangeError'
110+
});
111+
112+
assert.throws(common.mustCall(() => {
113+
https.createServer({
114+
...options,
115+
maxHeaderSize: ''
116+
}, serverCallback);
117+
}), {
118+
message: 'The "maxHeaderSize" argument must be of type number. ' +
119+
'Received type string (\'\')',
120+
code: 'ERR_INVALID_ARG_TYPE',
121+
name: 'TypeError'
122+
});
123+
}

0 commit comments

Comments
 (0)