http: optimize checkIsHttpToken for short strings · nodejs/node@83ae610
@@ -24,6 +24,7 @@
2424const {
2525 MathMin,
2626 Symbol,
27+ Uint8Array,
2728} = primordials;
2829const { setImmediate } = require('timers');
2930@@ -205,7 +206,30 @@ function freeParser(parser, req, socket) {
205206}
206207}
207208209+// Character code ranges for valid HTTP tokens
210+// Valid chars: ^_`a-zA-Z-0-9!#$%&'*+.|~
211+// Based on RFC 7230 Section 3.2.6 token definition
212+// See https://tools.ietf.org/html/rfc7230#section-3.2.6
208213const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
214+const validTokenChars = new Uint8Array([
215+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
216+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
217+0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32-47 (!"#$%&'()*+,-./)
218+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63 (0-9:;<=>?)
219+0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64-79 (@A-O)
220+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80-95 (P-Z[\]^_)
221+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96-111 (`a-o)
222+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112-127 (p-z{|}~)
223+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143
224+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159
225+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175
226+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191
227+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207
228+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223
229+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239
230+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-255
231+]);
232+209233/**
210234 * Verifies that the given val is a valid HTTP token
211235 * per the rules defined in RFC 7230
@@ -214,7 +238,19 @@ const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
214238 * @returns {boolean}
215239 */
216240function checkIsHttpToken(val) {
217-return tokenRegExp.test(val);
241+if (val.length >= 10) {
242+return tokenRegExp.test(val);
243+}
244+245+if (val.length === 0) return false;
246+247+// Use lookup table for short strings, regex for longer ones
248+for (let i = 0; i < val.length; i++) {
249+if (!validTokenChars[val.charCodeAt(i)]) {
250+return false;
251+}
252+}
253+return true;
218254}
219255220256const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;