@@ -15,6 +15,34 @@ const Agent = require('_http_agent');
15
15
const Buffer = require ( 'buffer' ) . Buffer ;
16
16
const urlToOptions = require ( 'internal/url' ) . urlToOptions ;
17
17
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
+
18
46
function ClientRequest ( options , cb ) {
19
47
var self = this ;
20
48
OutgoingMessage . call ( self ) ;
@@ -45,14 +73,20 @@ function ClientRequest(options, cb) {
45
73
if ( self . agent && self . agent . protocol )
46
74
expectedProtocol = self . agent . protocol ;
47
75
48
- if ( options . path && / [ \u0000 - \u0020 ] / . test ( options . path ) ) {
49
- // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
50
- // with an additional rule for ignoring percentage-escaped characters
51
- // but that's a) hard to capture in a regular expression that performs
52
- // well, and b) possibly too restrictive for real-world usage.
53
- // Restrict the filter to control characters and spaces.
54
- throw new TypeError ( 'Request path contains unescaped characters' ) ;
55
- } else if ( protocol !== expectedProtocol ) {
76
+ var path ;
77
+ if ( options . path ) {
78
+ path = '' + options . path ;
79
+ var invalidPath ;
80
+ if ( path . length <= 39 ) { // Determined experimentally in V8 5.4
81
+ invalidPath = isInvalidPath ( path ) ;
82
+ } else {
83
+ invalidPath = / [ \u0000 - \u0020 ] / . test ( path ) ;
84
+ }
85
+ if ( invalidPath )
86
+ throw new TypeError ( 'Request path contains unescaped characters' ) ;
87
+ }
88
+
89
+ if ( protocol !== expectedProtocol ) {
56
90
throw new Error ( 'Protocol "' + protocol + '" not supported. ' +
57
91
'Expected "' + expectedProtocol + '"' ) ;
58
92
}
0 commit comments