Skip to content

Commit 12e5405

Browse files
jasnelladuh95
authored andcommitted
benchmark: add http header validator benchmark
Compare http.isValidHeaderName() and http.isValidHeaderValue() with http.validateHeaderName() and http.validateHeaderValue() wrapped in try/catch, for valid and invalid input, and for both 'strict' and 'relaxed' header value validation. Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: #66334 Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Tim Perry <pimterry@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
1 parent e998d26 commit 12e5405

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

‎benchmark/http/is_valid_header.js‎

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
'use strict';
2+
3+
// Compares the non-throwing header validators (http.isValidHeaderName() and
4+
// http.isValidHeaderValue()) with the throwing ones (http.validateHeaderName()
5+
// and http.validateHeaderValue()) used inside try/catch.
6+
7+
const common = require('../common.js');
8+
const assert = require('assert');
9+
const {
10+
isValidHeaderName,
11+
isValidHeaderValue,
12+
validateHeaderName,
13+
validateHeaderValue,
14+
} = require('http');
15+
16+
const inputs = {
17+
name: {
18+
valid: [
19+
'ETag', 'date', 'Vary', 'server', 'Expires', 'location', 'Connection',
20+
'content-type', 'Cache-Control', 'content-length', 'x-frame-options',
21+
'Transfer-Encoding', 'x-request-id',
22+
],
23+
invalid: [
24+
'', ':', 'bad header', 'x-forwarded-fםr', '中文呢', '((((())))',
25+
':alternate-protocol', 'alternate-protocol:', 'x\r\ninjected',
26+
],
27+
},
28+
value: {
29+
valid: [
30+
'W/"2-d4cbb29"', 'OK', 'Express', 'application/json',
31+
'application/json; charset=utf-8', 'sessionid=; Path=/',
32+
'text/html; charset=utf-8', '10', 'max-age=0, no-cache', 'gzip, br',
33+
],
34+
// Invalid under both 'strict' and 'relaxed' validation.
35+
invalid: [
36+
'a\r\nb', 'value\n', 'cr\r', 'nul\0byte', 'לא תקין', 'emoji \u{1F600}',
37+
'x'.repeat(64) + '\r\n',
38+
],
39+
},
40+
};
41+
42+
const bench = common.createBenchmark(main, {
43+
method: [
44+
'isValidHeaderName',
45+
'validateHeaderName',
46+
'isValidHeaderValue',
47+
'validateHeaderValue',
48+
],
49+
input: ['valid', 'invalid'],
50+
httpValidation: ['strict', 'relaxed'],
51+
n: [1e6],
52+
}, {
53+
// httpValidation only applies to isValidHeaderValue().
54+
combinationFilter: (p) =>
55+
p.httpValidation === 'strict' || p.method === 'isValidHeaderValue',
56+
});
57+
58+
function main({ n, method, input, httpValidation }) {
59+
let valid = 0;
60+
61+
switch (method) {
62+
case 'isValidHeaderName': {
63+
const list = inputs.name[input];
64+
const len = list.length;
65+
bench.start();
66+
for (let i = 0; i < n; i++) {
67+
if (isValidHeaderName(list[i % len])) valid++;
68+
}
69+
bench.end(n);
70+
break;
71+
}
72+
case 'validateHeaderName': {
73+
const list = inputs.name[input];
74+
const len = list.length;
75+
bench.start();
76+
for (let i = 0; i < n; i++) {
77+
try {
78+
validateHeaderName(list[i % len]);
79+
valid++;
80+
} catch {
81+
// Invalid name.
82+
}
83+
}
84+
bench.end(n);
85+
break;
86+
}
87+
case 'isValidHeaderValue': {
88+
const list = inputs.value[input];
89+
const len = list.length;
90+
const options = httpValidation === 'strict' ? undefined : { httpValidation };
91+
bench.start();
92+
for (let i = 0; i < n; i++) {
93+
if (isValidHeaderValue(list[i % len], options)) valid++;
94+
}
95+
bench.end(n);
96+
break;
97+
}
98+
case 'validateHeaderValue': {
99+
const list = inputs.value[input];
100+
const len = list.length;
101+
bench.start();
102+
for (let i = 0; i < n; i++) {
103+
try {
104+
validateHeaderValue('x-header', list[i % len]);
105+
valid++;
106+
} catch {
107+
// Invalid value.
108+
}
109+
}
110+
bench.end(n);
111+
break;
112+
}
113+
default:
114+
throw new Error(`Unexpected method: ${method}`);
115+
}
116+
117+
// Consume the result so the loop cannot be optimized away, and make sure
118+
// the inputs are what they claim to be.
119+
assert.strictEqual(valid, input === 'valid' ? n : 0);
120+
}

0 commit comments

Comments
 (0)