From b1f8b707357db6a33bb9ae1dbcd386bee679a248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=A9=EC=A7=84=ED=98=81?= Date: Thu, 11 Sep 2025 05:41:14 +0900 Subject: [PATCH] http: optimize checkIsHttpToken for short strings Use lookup table instead of regex for strings shorter than 10 characters to improve performance for common short header names while maintaining compatibility. --- lib/_http_common.js | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/_http_common.js b/lib/_http_common.js index ae4cc39befa258..d64c95afab985c 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -24,6 +24,7 @@ const { MathMin, Symbol, + Uint8Array, } = primordials; const { setImmediate } = require('timers'); @@ -205,7 +206,30 @@ function freeParser(parser, req, socket) { } } +// Character code ranges for valid HTTP tokens +// Valid chars: ^_`a-zA-Z-0-9!#$%&'*+.|~ +// Based on RFC 7230 Section 3.2.6 token definition +// See https://tools.ietf.org/html/rfc7230#section-3.2.6 const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/; +const validTokenChars = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32-47 (!"#$%&'()*+,-./) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63 (0-9:;<=>?) + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64-79 (@A-O) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80-95 (P-Z[\]^_) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96-111 (`a-o) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112-127 (p-z{|}~) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-255 +]); + /** * Verifies that the given val is a valid HTTP token * per the rules defined in RFC 7230 @@ -214,7 +238,19 @@ const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/; * @returns {boolean} */ function checkIsHttpToken(val) { - return tokenRegExp.test(val); + if (val.length >= 10) { + return tokenRegExp.test(val); + } + + if (val.length === 0) return false; + + // Use lookup table for short strings, regex for longer ones + for (let i = 0; i < val.length; i++) { + if (!validTokenChars[val.charCodeAt(i)]) { + return false; + } + } + return true; } const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;