@@ -15,6 +15,34 @@ const Agent = require('_http_agent');
1515const Buffer = require ( 'buffer' ) . Buffer ;
1616
1717
18+ // The actual list of disallowed characters in regexp form is more like:
19+ // /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
20+ // with an additional rule for ignoring percentage-escaped characters, but
21+ // that's a) hard to capture in a regular expression that performs well, and
22+ // b) possibly too restrictive for real-world usage. So instead we restrict the
23+ // filter to just control characters and spaces.
24+ //
25+ // This function is used in the case of small paths, where manual character code
26+ // checks can greatly outperform the equivalent regexp (tested in V8 5.4).
27+ function isInvalidPath ( s ) {
28+ var i = 0 ;
29+ if ( s . charCodeAt ( 0 ) <= 32 ) return true ;
30+ if ( ++ i >= s . length ) return false ;
31+ if ( s . charCodeAt ( 1 ) <= 32 ) return true ;
32+ if ( ++ i >= s . length ) return false ;
33+ if ( s . charCodeAt ( 2 ) <= 32 ) return true ;
34+ if ( ++ i >= s . length ) return false ;
35+ if ( s . charCodeAt ( 3 ) <= 32 ) return true ;
36+ if ( ++ i >= s . length ) return false ;
37+ if ( s . charCodeAt ( 4 ) <= 32 ) return true ;
38+ if ( ++ i >= s . length ) return false ;
39+ if ( s . charCodeAt ( 5 ) <= 32 ) return true ;
40+ ++ i ;
41+ for ( ; i < s . length ; ++ i )
42+ if ( s . charCodeAt ( i ) <= 32 ) return true ;
43+ return false ;
44+ }
45+
1846function ClientRequest ( options , cb ) {
1947 var self = this ;
2048 OutgoingMessage . call ( self ) ;
@@ -43,14 +71,20 @@ function ClientRequest(options, cb) {
4371 if ( self . agent && self . agent . protocol )
4472 expectedProtocol = self . agent . protocol ;
4573
46- if ( options . path && / [ \u0000 - \u0020 ] / . test ( options . path ) ) {
47- // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
48- // with an additional rule for ignoring percentage-escaped characters
49- // but that's a) hard to capture in a regular expression that performs
50- // well, and b) possibly too restrictive for real-world usage.
51- // Restrict the filter to control characters and spaces.
52- throw new TypeError ( 'Request path contains unescaped characters' ) ;
53- } else if ( protocol !== expectedProtocol ) {
74+ var path ;
75+ if ( options . path ) {
76+ path = '' + options . path ;
77+ var invalidPath ;
78+ if ( path . length <= 39 ) { // Determined experimentally in V8 5.4
79+ invalidPath = isInvalidPath ( path ) ;
80+ } else {
81+ invalidPath = / [ \u0000 - \u0020 ] / . test ( path ) ;
82+ }
83+ if ( invalidPath )
84+ throw new TypeError ( 'Request path contains unescaped characters' ) ;
85+ }
86+
87+ if ( protocol !== expectedProtocol ) {
5488 throw new Error ( 'Protocol "' + protocol + '" not supported. ' +
5589 'Expected "' + expectedProtocol + '"' ) ;
5690 }
0 commit comments