File tree Expand file tree Collapse file tree 2 files changed +100
-2
lines changed Expand file tree Collapse file tree 2 files changed +100
-2
lines changed Original file line number Diff line number Diff line change 1+ 'use strict' ;
2+
3+ const common = require ( '../common.js' ) ;
4+ const _checkIsHttpToken = require ( '_http_common' ) . _checkIsHttpToken ;
5+
6+ const bench = common . createBenchmark ( main , {
7+ key : [
8+ 'TCN' ,
9+ 'ETag' ,
10+ 'date' ,
11+ 'Vary' ,
12+ 'server' ,
13+ 'Server' ,
14+ 'status' ,
15+ 'version' ,
16+ 'Expires' ,
17+ 'alt-svc' ,
18+ 'location' ,
19+ 'Connection' ,
20+ 'Keep-Alive' ,
21+ 'content-type' ,
22+ 'Content-Type' ,
23+ 'Cache-Control' ,
24+ 'Last-Modified' ,
25+ 'Accept-Ranges' ,
26+ 'content-length' ,
27+ 'x-frame-options' ,
28+ 'x-xss-protection' ,
29+ 'Content-Encoding' ,
30+ 'Content-Location' ,
31+ 'Transfer-Encoding' ,
32+ 'alternate-protocol' ,
33+ ':' , // invalid input
34+ '@@' ,
35+ '中文呢' , // unicode
36+ '((((())))' , // invalid
37+ ':alternate-protocol' , // fast bailout
38+ 'alternate-protocol:' // slow bailout
39+ ] ,
40+ n : [ 1e6 ] ,
41+ } ) ;
42+
43+ function main ( conf ) {
44+ var n = + conf . n ;
45+ var key = conf . key ;
46+
47+ bench . start ( ) ;
48+ for ( var i = 0 ; i < n ; i ++ ) {
49+ _checkIsHttpToken ( key ) ;
50+ }
51+ bench . end ( n ) ;
52+ }
Original file line number Diff line number Diff line change @@ -225,10 +225,56 @@ exports.httpSocketSetup = httpSocketSetup;
225225/**
226226 * Verifies that the given val is a valid HTTP token
227227 * per the rules defined in RFC 7230
228+ * See https://tools.ietf.org/html/rfc7230#section-3.2.6
229+ *
230+ * This implementation of checkIsHttpToken() loops over the string instead of
231+ * using a regular expression since the former is up to 180% faster with v8 4.9
232+ * depending on the string length (the shorter the string, the larger the
233+ * performance difference)
228234 **/
229- const token = / ^ [ a - z A - Z 0 - 9 _ ! # $ % & ' * + . ^ ` | ~ - ] + $ / ;
230235function checkIsHttpToken ( val ) {
231- return typeof val === 'string' && token . test ( val ) ;
236+ if ( typeof val !== 'string' || val . length === 0 )
237+ return false ;
238+
239+ for ( var i = 0 , len = val . length ; i < len ; i ++ ) {
240+ var ch = val . charCodeAt ( i ) ;
241+
242+ if ( ch >= 65 && ch <= 90 ) // A-Z
243+ continue ;
244+
245+ if ( ch >= 97 && ch <= 122 ) // a-z
246+ continue ;
247+
248+ // ^ => 94
249+ // _ => 95
250+ // ` => 96
251+ // | => 124
252+ // ~ => 126
253+ if ( ch === 94 || ch === 95 || ch === 96 || ch === 124 || ch === 126 )
254+ continue ;
255+
256+ if ( ch >= 48 && ch <= 57 ) // 0-9
257+ continue ;
258+
259+ // ! => 33
260+ // # => 35
261+ // $ => 36
262+ // % => 37
263+ // & => 38
264+ // ' => 39
265+ // * => 42
266+ // + => 43
267+ // - => 45
268+ // . => 46
269+ if ( ch >= 33 && ch <= 46 ) {
270+ if ( ch === 34 || ch === 40 || ch === 41 || ch === 44 )
271+ return false ;
272+ continue ;
273+ }
274+
275+ return false ;
276+ }
277+ return true ;
232278}
233279exports . _checkIsHttpToken = checkIsHttpToken ;
234280
You can’t perform that action at this time.
0 commit comments