mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 22:01:47 +00:00
Compare commits
95 Commits
mock-dot-c
...
ciro/http2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f727a06a63 | ||
|
|
ea2a41bf15 | ||
|
|
e23701e6fd | ||
|
|
3a78d28931 | ||
|
|
ce0655f1a8 | ||
|
|
862b94a235 | ||
|
|
b44daf72bc | ||
|
|
e5b818b2cc | ||
|
|
b3438e7a0d | ||
|
|
bec13e2d4a | ||
|
|
637961e385 | ||
|
|
d3ff571d3e | ||
|
|
9bd3aa0434 | ||
|
|
35a242280b | ||
|
|
88984b7ccf | ||
|
|
70d80c8c15 | ||
|
|
e9e5714d94 | ||
|
|
5cf5bc5c6f | ||
|
|
77dff097dd | ||
|
|
f05635951c | ||
|
|
491fd99192 | ||
|
|
6d339e7aa5 | ||
|
|
aef0087097 | ||
|
|
d94bc310e7 | ||
|
|
bd93866976 | ||
|
|
929b7c78ce | ||
|
|
d0230299a9 | ||
|
|
9c6d3c37b7 | ||
|
|
a47c15e32a | ||
|
|
b9c3440932 | ||
|
|
a953934bd8 | ||
|
|
f1b4e42b80 | ||
|
|
da8e274c68 | ||
|
|
eec455b0ff | ||
|
|
7b247d60fb | ||
|
|
1dea06d0f2 | ||
|
|
6cc40db1b2 | ||
|
|
54c2174d06 | ||
|
|
49b80a8480 | ||
|
|
1eb0fc5d74 | ||
|
|
4bdd5f0b5f | ||
|
|
6a6ca7517c | ||
|
|
a60252ee75 | ||
|
|
f4ca604af9 | ||
|
|
e649fc3ec1 | ||
|
|
e1a2fcf93b | ||
|
|
53c59ee348 | ||
|
|
aecaa7242c | ||
|
|
04ec8a81e1 | ||
|
|
bd69a85fc5 | ||
|
|
fcef720d48 | ||
|
|
c54a739d28 | ||
|
|
3f3cbefbc2 | ||
|
|
04dd0f6ecf | ||
|
|
139fc76166 | ||
|
|
81d2141d6a | ||
|
|
ec9e318c6f | ||
|
|
1c48c251a2 | ||
|
|
a7b0cf9d8b | ||
|
|
1791a5b589 | ||
|
|
abed93168b | ||
|
|
ab523d523b | ||
|
|
0e68af960d | ||
|
|
f1cf05cba6 | ||
|
|
db33b3568c | ||
|
|
a767618ccf | ||
|
|
4de68eda5b | ||
|
|
2f81cc7ddd | ||
|
|
5aae453c80 | ||
|
|
a9d23f1908 | ||
|
|
eb26c3edf9 | ||
|
|
822e3b8cf0 | ||
|
|
f451ddb910 | ||
|
|
7da15d4e72 | ||
|
|
6e3ef2dc28 | ||
|
|
6cee7c0ec1 | ||
|
|
b1846a0c69 | ||
|
|
8f81e77a6f | ||
|
|
3b1e194103 | ||
|
|
43cff4bc42 | ||
|
|
d3ba69ba47 | ||
|
|
7ddd568f4f | ||
|
|
9f8d5caf07 | ||
|
|
a92975828e | ||
|
|
43769fd805 | ||
|
|
59acf758d7 | ||
|
|
43a606fad6 | ||
|
|
9e0bc5e5c7 | ||
|
|
ea50253dbe | ||
|
|
50de52b35a | ||
|
|
1bc6eb5464 | ||
|
|
40ce107f32 | ||
|
|
f3502a0319 | ||
|
|
7c665caed3 | ||
|
|
6f7f6af643 |
@@ -0,0 +1,120 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const h2 = require('http2');
|
||||
|
||||
const server = h2.createServer();
|
||||
|
||||
// We use the lower-level API here
|
||||
server.on('stream', common.mustCall((stream, headers, flags) => {
|
||||
stream.respond();
|
||||
stream.end('ok');
|
||||
}));
|
||||
server.on('session', common.mustCall((session) => {
|
||||
session.on('remoteSettings', common.mustCall(2));
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = h2.connect(`http://127.0.0.1:${server.address().port}`);
|
||||
|
||||
[
|
||||
['headerTableSize', -1, RangeError],
|
||||
['headerTableSize', 2 ** 32, RangeError],
|
||||
['initialWindowSize', -1, RangeError],
|
||||
['initialWindowSize', 2 ** 32, RangeError],
|
||||
['maxFrameSize', 1, RangeError],
|
||||
['maxFrameSize', 2 ** 24, RangeError],
|
||||
['maxConcurrentStreams', -1, RangeError],
|
||||
['maxConcurrentStreams', 2 ** 32, RangeError],
|
||||
['maxHeaderListSize', -1, RangeError],
|
||||
['maxHeaderListSize', 2 ** 32, RangeError],
|
||||
['maxHeaderSize', -1, RangeError],
|
||||
['maxHeaderSize', 2 ** 32, RangeError],
|
||||
['enablePush', 'a', TypeError],
|
||||
['enablePush', 1, TypeError],
|
||||
['enablePush', 0, TypeError],
|
||||
['enablePush', null, TypeError],
|
||||
['enablePush', {}, TypeError],
|
||||
].forEach(([name, value, errorType]) =>
|
||||
assert.throws(
|
||||
() => client.settings({ [name]: value }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: errorType.name
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
0x11: 5,
|
||||
0x12: 5,
|
||||
0x13: 5,
|
||||
0x14: 5,
|
||||
0x15: 5,
|
||||
0x16: 5,
|
||||
0x17: 5,
|
||||
0x18: 5,
|
||||
0x19: 5,
|
||||
0x1A: 5, // more than 10
|
||||
0x1B: 5
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS',
|
||||
name: 'Error'
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
0x10000: 5,
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
0x55: 0x100000000,
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
0x55: -1,
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
}
|
||||
);
|
||||
|
||||
[1, true, {}, []].forEach((invalidCallback) =>
|
||||
assert.throws(
|
||||
() => client.settings({}, invalidCallback),
|
||||
{
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
client.settings({ maxFrameSize: 1234567, customSettings: { 0xbf: 12 } });
|
||||
|
||||
const req = client.request();
|
||||
req.on('response', common.mustCall());
|
||||
req.resume();
|
||||
req.on('close', common.mustCall(() => {
|
||||
server.close();
|
||||
client.close();
|
||||
}));
|
||||
}));
|
||||
340
test/js/node/test/parallel/test-http2-getpackedsettings.js
Normal file
340
test/js/node/test/parallel/test-http2-getpackedsettings.js
Normal file
@@ -0,0 +1,340 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
|
||||
const check = Buffer.from([0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x03, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x04, 0x00, 0x00, 0xff, 0xff,
|
||||
0x00, 0x05, 0x00, 0x00, 0x40, 0x00,
|
||||
0x00, 0x06, 0x00, 0x00, 0xff, 0xff,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
|
||||
const val = http2.getPackedSettings(http2.getDefaultSettings());
|
||||
assert.deepStrictEqual(val, check);
|
||||
|
||||
[
|
||||
['headerTableSize', 0],
|
||||
['headerTableSize', 2 ** 32 - 1],
|
||||
['initialWindowSize', 0],
|
||||
['initialWindowSize', 2 ** 32 - 1],
|
||||
['maxFrameSize', 16384],
|
||||
['maxFrameSize', 2 ** 24 - 1],
|
||||
['maxConcurrentStreams', 0],
|
||||
['maxConcurrentStreams', 2 ** 31 - 1],
|
||||
['maxHeaderListSize', 0],
|
||||
['maxHeaderListSize', 2 ** 32 - 1],
|
||||
['maxHeaderSize', 0],
|
||||
['maxHeaderSize', 2 ** 32 - 1],
|
||||
['customSettings', { '9999': 301 }],
|
||||
].forEach((i) => {
|
||||
// Valid options should not throw.
|
||||
http2.getPackedSettings({ [i[0]]: i[1] });
|
||||
});
|
||||
|
||||
http2.getPackedSettings({ enablePush: true });
|
||||
http2.getPackedSettings({ enablePush: false });
|
||||
|
||||
[
|
||||
['headerTableSize', -1],
|
||||
['headerTableSize', 2 ** 32],
|
||||
['initialWindowSize', -1],
|
||||
['initialWindowSize', 2 ** 32],
|
||||
['maxFrameSize', 16383],
|
||||
['maxFrameSize', 2 ** 24],
|
||||
['maxConcurrentStreams', -1],
|
||||
['maxConcurrentStreams', 2 ** 32],
|
||||
['maxHeaderListSize', -1],
|
||||
['maxHeaderListSize', 2 ** 32],
|
||||
['maxHeaderSize', -1],
|
||||
['maxHeaderSize', 2 ** 32],
|
||||
].forEach((i) => {
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({ [i[0]]: i[1] });
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError',
|
||||
message: `Invalid value for setting "${i[0]}": ${i[1]}`
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
1, null, '', Infinity, new Date(), {}, NaN, [false],
|
||||
].forEach((i) => {
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({ enablePush: i });
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'TypeError',
|
||||
message: `Invalid value for setting "enablePush": ${i}`
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
1, null, '', Infinity, new Date(), {}, NaN, [false],
|
||||
].forEach((i) => {
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({ enableConnectProtocol: i });
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'TypeError',
|
||||
message: `Invalid value for setting "enableConnectProtocol": ${i}`
|
||||
});
|
||||
});
|
||||
|
||||
{
|
||||
const check = Buffer.from([
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
|
||||
0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x27, 0x0F, 0x00, 0x00, 0x01, 0x2d,
|
||||
]);
|
||||
|
||||
const packed = http2.getPackedSettings({
|
||||
headerTableSize: 100,
|
||||
initialWindowSize: 100,
|
||||
maxFrameSize: 20000,
|
||||
maxConcurrentStreams: 200,
|
||||
maxHeaderListSize: 100,
|
||||
maxHeaderSize: 100,
|
||||
enablePush: true,
|
||||
enableConnectProtocol: false,
|
||||
foo: 'ignored',
|
||||
customSettings: { '9999': 301 }
|
||||
});
|
||||
assert.strictEqual(packed.length, 48);
|
||||
assert.deepStrictEqual(packed, check);
|
||||
}
|
||||
|
||||
// Check if multiple custom settings can be set
|
||||
{
|
||||
const check = Buffer.from([
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
|
||||
0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0xf3, 0x00, 0x00, 0x07, 0x9F,
|
||||
0x0a, 0x2e, 0x00, 0x00, 0x00, 0x58,
|
||||
]);
|
||||
|
||||
const packed = http2.getPackedSettings({
|
||||
headerTableSize: 100,
|
||||
initialWindowSize: 100,
|
||||
maxFrameSize: 20000,
|
||||
maxConcurrentStreams: 200,
|
||||
maxHeaderListSize: 100,
|
||||
maxHeaderSize: 100,
|
||||
enablePush: true,
|
||||
enableConnectProtocol: false,
|
||||
customSettings: { '2606': 88, '1011': 1951 }
|
||||
});
|
||||
assert.strictEqual(packed.length, 54);
|
||||
assert.deepStrictEqual(packed, check);
|
||||
}
|
||||
|
||||
{
|
||||
// Check if wrong custom settings cause an error
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({
|
||||
customSettings: { '-1': 659685 }
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({
|
||||
customSettings: { '10': 34577577777 }
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({
|
||||
customSettings: { 'notvalid': -777 }
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({
|
||||
customSettings: { '11': 11, '12': 12, '13': 13, '14': 14, '15': 15, '16': 16,
|
||||
'17': 17, '18': 18, '19': 19, '20': 20, '21': 21 }
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS'
|
||||
});
|
||||
assert.throws(() => {
|
||||
http2.getPackedSettings({
|
||||
customSettings: { '11': 11, '12': 12, '13': 13, '14': 14, '15': 15, '16': 16,
|
||||
'17': 17, '18': 18, '19': 19, '20': 20, '21': 21, '22': 22 }
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for not passing settings.
|
||||
{
|
||||
const packed = http2.getPackedSettings();
|
||||
assert.strictEqual(packed.length, 0);
|
||||
}
|
||||
|
||||
{
|
||||
const packed = Buffer.from([
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
|
||||
0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x27, 0x0F, 0x00, 0x00, 0x01, 0x2d]);
|
||||
|
||||
[1, true, '', [], {}, NaN].forEach((input) => {
|
||||
assert.throws(() => {
|
||||
http2.getUnpackedSettings(input);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message:
|
||||
'The "buf" argument must be an instance of Buffer or TypedArray.' +
|
||||
common.invalidArgTypeHelper(input)
|
||||
});
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getUnpackedSettings(packed.slice(5));
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH',
|
||||
name: 'RangeError',
|
||||
message: 'Packed settings length must be a multiple of six'
|
||||
});
|
||||
|
||||
const settings = http2.getUnpackedSettings(packed);
|
||||
|
||||
assert(settings);
|
||||
assert.strictEqual(settings.headerTableSize, 100);
|
||||
assert.strictEqual(settings.initialWindowSize, 100);
|
||||
assert.strictEqual(settings.maxFrameSize, 20000);
|
||||
assert.strictEqual(settings.maxConcurrentStreams, 200);
|
||||
assert.strictEqual(settings.maxHeaderListSize, 100);
|
||||
assert.strictEqual(settings.maxHeaderSize, 100);
|
||||
assert.strictEqual(settings.enablePush, true);
|
||||
assert.strictEqual(settings.enableConnectProtocol, false);
|
||||
assert.deepStrictEqual(settings.customSettings, { '9999': 301 });
|
||||
}
|
||||
|
||||
{
|
||||
const packed = new Uint16Array([
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
|
||||
0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getUnpackedSettings(packed.slice(5));
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH',
|
||||
name: 'RangeError',
|
||||
message: 'Packed settings length must be a multiple of six'
|
||||
});
|
||||
|
||||
const settings = http2.getUnpackedSettings(packed);
|
||||
|
||||
assert(settings);
|
||||
assert.strictEqual(settings.headerTableSize, 100);
|
||||
assert.strictEqual(settings.initialWindowSize, 100);
|
||||
assert.strictEqual(settings.maxFrameSize, 20000);
|
||||
assert.strictEqual(settings.maxConcurrentStreams, 200);
|
||||
assert.strictEqual(settings.maxHeaderListSize, 100);
|
||||
assert.strictEqual(settings.maxHeaderSize, 100);
|
||||
assert.strictEqual(settings.enablePush, true);
|
||||
assert.strictEqual(settings.enableConnectProtocol, false);
|
||||
}
|
||||
|
||||
{
|
||||
const packed = new DataView(Buffer.from([
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
|
||||
0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00]).buffer);
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getUnpackedSettings(packed);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message:
|
||||
'The "buf" argument must be an instance of Buffer or TypedArray.' +
|
||||
common.invalidArgTypeHelper(packed)
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const packed = Buffer.from([
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
|
||||
|
||||
const settings = http2.getUnpackedSettings(packed, { validate: true });
|
||||
assert.strictEqual(settings.enablePush, false);
|
||||
assert.strictEqual(settings.enableConnectProtocol, false);
|
||||
}
|
||||
{
|
||||
const packed = Buffer.from([
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x64]);
|
||||
|
||||
const settings = http2.getUnpackedSettings(packed, { validate: true });
|
||||
assert.strictEqual(settings.enablePush, true);
|
||||
assert.strictEqual(settings.enableConnectProtocol, true);
|
||||
}
|
||||
|
||||
// Verify that passing {validate: true} does not throw.
|
||||
{
|
||||
const packed = Buffer.from([
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0xc8,
|
||||
0x00, 0x05, 0x00, 0x00, 0x4e, 0x20,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x06, 0x00, 0x00, 0x00, 0x64,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00]);
|
||||
|
||||
http2.getUnpackedSettings(packed, { validate: true });
|
||||
}
|
||||
|
||||
// Check for maxFrameSize failing the max number.
|
||||
{
|
||||
const packed = Buffer.from([0x00, 0x05, 0x01, 0x00, 0x00, 0x00]);
|
||||
|
||||
assert.throws(() => {
|
||||
http2.getUnpackedSettings(packed, { validate: true });
|
||||
}, {
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError',
|
||||
message: 'Invalid value for setting "maxFrameSize": 16777216'
|
||||
});
|
||||
}
|
||||
80
test/js/node/test/parallel/test-http2-misc-util.js
Normal file
80
test/js/node/test/parallel/test-http2-misc-util.js
Normal file
@@ -0,0 +1,80 @@
|
||||
// Flags: --expose-internals
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
|
||||
const {
|
||||
assertIsObject,
|
||||
assertWithinRange,
|
||||
sessionName,
|
||||
assertIsArray
|
||||
} = require('internal/http2/util');
|
||||
|
||||
// Code coverage for sessionName utility function
|
||||
assert.strictEqual(sessionName(0), 'server');
|
||||
assert.strictEqual(sessionName(1), 'client');
|
||||
[2, '', 'test', {}, [], true].forEach((i) => {
|
||||
assert.strictEqual(sessionName(2), '<invalid>');
|
||||
});
|
||||
|
||||
// Code coverage for assertWithinRange function
|
||||
assert.throws(
|
||||
() => assertWithinRange('test', -1),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError',
|
||||
message: 'Invalid value for setting "test": -1'
|
||||
});
|
||||
|
||||
assertWithinRange('test', 1);
|
||||
|
||||
assert.throws(
|
||||
() => assertIsObject('foo', 'test'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "test" argument must be of type object. Received ' +
|
||||
"type string ('foo')"
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => assertIsObject('foo', 'test', ['Date']),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "test" argument must be an instance of Date. Received type ' +
|
||||
"string ('foo')"
|
||||
});
|
||||
|
||||
assertIsObject({}, 'test');
|
||||
|
||||
assert.throws(
|
||||
() => assertIsArray('foo', 'test'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "test" argument must be an instance of Array. Received type ' +
|
||||
"string ('foo')"
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => assertIsArray({}, 'test'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "test" argument must be an instance of Array. Received an instance of Object'
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => assertIsArray(1, 'test'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "test" argument must be an instance of Array. Received type ' +
|
||||
'number (1)'
|
||||
}
|
||||
);
|
||||
|
||||
assertIsArray([], 'test');
|
||||
208
test/js/node/test/parallel/test-http2-session-settings.js
Normal file
208
test/js/node/test/parallel/test-http2-session-settings.js
Normal file
@@ -0,0 +1,208 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const h2 = require('http2');
|
||||
|
||||
const server = h2.createServer({
|
||||
remoteCustomSettings: [
|
||||
55,
|
||||
],
|
||||
settings: {
|
||||
customSettings: {
|
||||
1244: 456
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.on(
|
||||
'stream',
|
||||
common.mustCall((stream) => {
|
||||
const assertSettings = (settings) => {
|
||||
assert.strictEqual(typeof settings, 'object');
|
||||
assert.strictEqual(typeof settings.headerTableSize, 'number');
|
||||
assert.strictEqual(typeof settings.enablePush, 'boolean');
|
||||
assert.strictEqual(typeof settings.initialWindowSize, 'number');
|
||||
assert.strictEqual(typeof settings.maxFrameSize, 'number');
|
||||
assert.strictEqual(typeof settings.maxConcurrentStreams, 'number');
|
||||
assert.strictEqual(typeof settings.maxHeaderListSize, 'number');
|
||||
assert.strictEqual(typeof settings.maxHeaderSize, 'number');
|
||||
assert.strictEqual(typeof settings.customSettings, 'object');
|
||||
let countCustom = 0;
|
||||
if (settings.customSettings[55]) {
|
||||
assert.strictEqual(typeof settings.customSettings[55], 'number');
|
||||
assert.strictEqual(settings.customSettings[55], 12);
|
||||
countCustom++;
|
||||
}
|
||||
if (settings.customSettings[155]) {
|
||||
// Should not happen actually
|
||||
assert.strictEqual(typeof settings.customSettings[155], 'number');
|
||||
countCustom++;
|
||||
}
|
||||
if (settings.customSettings[1244]) {
|
||||
assert.strictEqual(typeof settings.customSettings[1244], 'number');
|
||||
assert.strictEqual(settings.customSettings[1244], 456);
|
||||
countCustom++;
|
||||
}
|
||||
assert.strictEqual(countCustom, 1);
|
||||
};
|
||||
|
||||
const localSettings = stream.session.localSettings;
|
||||
const remoteSettings = stream.session.remoteSettings;
|
||||
assertSettings(localSettings);
|
||||
assertSettings(remoteSettings);
|
||||
|
||||
// Test that stored settings are returned when called for second time
|
||||
assert.strictEqual(stream.session.localSettings, localSettings);
|
||||
assert.strictEqual(stream.session.remoteSettings, remoteSettings);
|
||||
|
||||
stream.respond({
|
||||
'content-type': 'text/html',
|
||||
':status': 200
|
||||
});
|
||||
stream.end('hello world');
|
||||
})
|
||||
);
|
||||
|
||||
server.on('session', (session) => {
|
||||
session.settings({
|
||||
maxConcurrentStreams: 2
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(
|
||||
0,
|
||||
common.mustCall(() => {
|
||||
const client = h2.connect(`http://127.0.0.1:${server.address().port}`, {
|
||||
settings: {
|
||||
enablePush: false,
|
||||
initialWindowSize: 123456,
|
||||
customSettings: {
|
||||
55: 12,
|
||||
155: 144 // should not arrive
|
||||
},
|
||||
},
|
||||
remoteCustomSettings: [
|
||||
1244,
|
||||
]
|
||||
});
|
||||
|
||||
client.on(
|
||||
'localSettings',
|
||||
common.mustCall((settings) => {
|
||||
assert(settings);
|
||||
assert.strictEqual(settings.enablePush, false);
|
||||
assert.strictEqual(settings.initialWindowSize, 123456);
|
||||
assert.strictEqual(settings.maxFrameSize, 16384);
|
||||
assert.strictEqual(settings.customSettings[55], 12);
|
||||
}, 2)
|
||||
);
|
||||
|
||||
let calledOnce = false;
|
||||
client.on(
|
||||
'remoteSettings',
|
||||
common.mustCall((settings) => {
|
||||
assert(settings);
|
||||
assert.strictEqual(
|
||||
settings.maxConcurrentStreams,
|
||||
calledOnce ? 2 : (2 ** 32) - 1
|
||||
);
|
||||
calledOnce = true;
|
||||
}, 2)
|
||||
);
|
||||
|
||||
const headers = { ':path': '/' };
|
||||
|
||||
const req = client.request(headers);
|
||||
|
||||
req.on('ready', common.mustCall(() => {
|
||||
// pendingSettingsAck will be true if a SETTINGS frame
|
||||
// has been sent but we are still waiting for an acknowledgement
|
||||
assert(client.pendingSettingsAck);
|
||||
}));
|
||||
|
||||
// State will only be valid after connect event is emitted
|
||||
req.on('ready', common.mustCall(() => {
|
||||
client.settings({ maxHeaderListSize: 1 }, common.mustCall());
|
||||
|
||||
// Verify valid error ranges
|
||||
[
|
||||
['headerTableSize', -1],
|
||||
['headerTableSize', 2 ** 32],
|
||||
['initialWindowSize', -1],
|
||||
['initialWindowSize', 2 ** 32],
|
||||
['maxFrameSize', 16383],
|
||||
['maxFrameSize', 2 ** 24],
|
||||
['maxHeaderListSize', -1],
|
||||
['maxHeaderListSize', 2 ** 32],
|
||||
['maxHeaderSize', -1],
|
||||
['maxHeaderSize', 2 ** 32],
|
||||
].forEach(([key, value]) => {
|
||||
const settings = {};
|
||||
settings[key] = value;
|
||||
assert.throws(
|
||||
() => client.settings(settings),
|
||||
{
|
||||
name: 'RangeError',
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
message: `Invalid value for setting "${key}": ${value}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Same tests as for the client on customSettings
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
0x10000: 5,
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
55: 0x100000000,
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => client.settings({ customSettings: {
|
||||
55: -1,
|
||||
} }),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
}
|
||||
);
|
||||
|
||||
// Error checks for enablePush
|
||||
[1, {}, 'test', [], null, Infinity, NaN].forEach((i) => {
|
||||
assert.throws(
|
||||
() => client.settings({ enablePush: i }),
|
||||
{
|
||||
name: 'TypeError',
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
message: `Invalid value for setting "enablePush": ${i}`
|
||||
}
|
||||
);
|
||||
});
|
||||
}));
|
||||
|
||||
req.on('response', common.mustCall());
|
||||
req.resume();
|
||||
req.on('end', common.mustCall(() => {
|
||||
server.close();
|
||||
client.close();
|
||||
}));
|
||||
req.end();
|
||||
})
|
||||
);
|
||||
60
test/js/node/test/parallel/test-http2-update-settings.js
Normal file
60
test/js/node/test/parallel/test-http2-update-settings.js
Normal file
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
// This test ensures that the Http2SecureServer and Http2Server
|
||||
// settings are updated when the setting object is valid.
|
||||
// When the setting object is invalid, this test ensures that
|
||||
// updateSettings throws an exception.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) { common.skip('missing crypto'); }
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
|
||||
testUpdateSettingsWith({
|
||||
server: http2.createSecureServer(),
|
||||
newServerSettings: {
|
||||
'headerTableSize': 1,
|
||||
'initialWindowSize': 1,
|
||||
'maxConcurrentStreams': 1,
|
||||
'maxHeaderListSize': 1,
|
||||
'maxFrameSize': 16385,
|
||||
'enablePush': false,
|
||||
'enableConnectProtocol': true,
|
||||
'customSettings': { '9999': 301 }
|
||||
}
|
||||
});
|
||||
testUpdateSettingsWith({
|
||||
server: http2.createServer(),
|
||||
newServerSettings: {
|
||||
'enablePush': false
|
||||
}
|
||||
});
|
||||
|
||||
function testUpdateSettingsWith({ server, newServerSettings }) {
|
||||
const oldServerSettings = getServerSettings(server);
|
||||
assert.notDeepStrictEqual(oldServerSettings, newServerSettings);
|
||||
server.updateSettings(newServerSettings);
|
||||
const updatedServerSettings = getServerSettings(server);
|
||||
assert.deepStrictEqual(updatedServerSettings, { ...oldServerSettings,
|
||||
...newServerSettings });
|
||||
assert.throws(() => server.updateSettings(''), {
|
||||
message: 'The "settings" argument must be of type object. ' +
|
||||
'Received type string (\'\')',
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
assert.throws(() => server.updateSettings({
|
||||
'maxHeaderListSize': 'foo'
|
||||
}), {
|
||||
message: 'Invalid value for setting "maxHeaderListSize": foo',
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
name: 'RangeError'
|
||||
});
|
||||
}
|
||||
|
||||
function getServerSettings(server) {
|
||||
const options = Object
|
||||
.getOwnPropertySymbols(server)
|
||||
.find((s) => s.toString() === 'Symbol(options)');
|
||||
return server[options].settings;
|
||||
}
|
||||
45
test/js/node/test/parallel/test-http2-util-asserts.js
Normal file
45
test/js/node/test/parallel/test-http2-util-asserts.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// Flags: --expose-internals
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const {
|
||||
assertIsObject,
|
||||
assertWithinRange,
|
||||
} = require('internal/http2/util');
|
||||
|
||||
[
|
||||
undefined,
|
||||
{},
|
||||
{ __proto__: null },
|
||||
new Date(),
|
||||
new (class Foo {})(),
|
||||
].forEach((input) => {
|
||||
assertIsObject(input, 'foo', 'Object');
|
||||
});
|
||||
|
||||
[
|
||||
1,
|
||||
false,
|
||||
'hello',
|
||||
NaN,
|
||||
Infinity,
|
||||
[],
|
||||
[{}],
|
||||
].forEach((input) => {
|
||||
assert.throws(
|
||||
() => assertIsObject(input, 'foo', 'Object'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "foo" argument must be of type object.' +
|
||||
common.invalidArgTypeHelper(input)
|
||||
});
|
||||
});
|
||||
|
||||
assertWithinRange('foo', 1, 0, 2);
|
||||
|
||||
assert.throws(() => assertWithinRange('foo', 1, 2, 3),
|
||||
{
|
||||
code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
|
||||
message: 'Invalid value for setting "foo": 1'
|
||||
});
|
||||
Reference in New Issue
Block a user