Skip to content

Commit

Permalink
http: optimize checkIsHttpToken()
Browse files Browse the repository at this point in the history
This commit both makes checkIsHttpToken() inlinable and extracts
the character checking logic to a separate inlinable function so that
the main loop can be unrolled a bit.

PR-URL: #6570
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com>
  • Loading branch information
mscdex authored and evanlucas committed Jun 16, 2016
1 parent 23a495a commit 4a63be0
Showing 1 changed file with 49 additions and 36 deletions.
85 changes: 49 additions & 36 deletions lib/_http_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,52 +232,65 @@ exports.httpSocketSetup = httpSocketSetup;
* per the rules defined in RFC 7230
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
*
* Allowed characters in an HTTP token:
* ^_`a-z 94-122
* A-Z 65-90
* - 45
* 0-9 48-57
* ! 33
* #$%&' 35-39
* *+ 42-43
* . 46
* | 124
* ~ 126
*
* This implementation of checkIsHttpToken() loops over the string instead of
* using a regular expression since the former is up to 180% faster with v8 4.9
* depending on the string length (the shorter the string, the larger the
* performance difference)
*
* Additionally, checkIsHttpToken() is currently designed to be inlinable by v8,
* so take care when making changes to the implementation so that the source
* code size does not exceed v8's default max_inlined_source_size setting.
**/
function isValidTokenChar(ch) {
if (ch >= 94 && ch <= 122)
return true;
if (ch >= 65 && ch <= 90)
return true;
if (ch === 45)
return true;
if (ch >= 48 && ch <= 57)
return true;
if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
return false;
if (ch >= 33 && ch <= 46)
return true;
if (ch === 124 || ch === 126)
return true;
return false;
}
function checkIsHttpToken(val) {
if (typeof val !== 'string' || val.length === 0)
return false;

for (var i = 0, len = val.length; i < len; i++) {
var ch = val.charCodeAt(i);

if (ch >= 65 && ch <= 90) // A-Z
continue;

if (ch >= 97 && ch <= 122) // a-z
continue;

// ^ => 94
// _ => 95
// ` => 96
// | => 124
// ~ => 126
if (ch === 94 || ch === 95 || ch === 96 || ch === 124 || ch === 126)
continue;

if (ch >= 48 && ch <= 57) // 0-9
continue;

// ! => 33
// # => 35
// $ => 36
// % => 37
// & => 38
// ' => 39
// * => 42
// + => 43
// - => 45
// . => 46
if (ch >= 33 && ch <= 46) {
if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
if (!isValidTokenChar(val.charCodeAt(0)))
return false;
const len = val.length;
if (len > 1) {
if (!isValidTokenChar(val.charCodeAt(1)))
return false;
if (len > 2) {
if (!isValidTokenChar(val.charCodeAt(2)))
return false;
continue;
if (len > 3) {
if (!isValidTokenChar(val.charCodeAt(3)))
return false;
for (var i = 4; i < len; i++) {
if (!isValidTokenChar(val.charCodeAt(i)))
return false;
}
}
}

return false;
}
return true;
}
Expand Down

0 comments on commit 4a63be0

Please sign in to comment.