|
|
@ -15,6 +15,34 @@ const Agent = require('_http_agent'); |
|
|
|
const Buffer = require('buffer').Buffer; |
|
|
|
const urlToOptions = require('internal/url').urlToOptions; |
|
|
|
|
|
|
|
// The actual list of disallowed characters in regexp form is more like:
|
|
|
|
// /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
|
|
|
|
// with an additional rule for ignoring percentage-escaped characters, but
|
|
|
|
// that's a) hard to capture in a regular expression that performs well, and
|
|
|
|
// b) possibly too restrictive for real-world usage. So instead we restrict the
|
|
|
|
// filter to just control characters and spaces.
|
|
|
|
//
|
|
|
|
// This function is used in the case of small paths, where manual character code
|
|
|
|
// checks can greatly outperform the equivalent regexp (tested in V8 5.4).
|
|
|
|
function isInvalidPath(s) { |
|
|
|
var i = 0; |
|
|
|
if (s.charCodeAt(0) <= 32) return true; |
|
|
|
if (++i >= s.length) return false; |
|
|
|
if (s.charCodeAt(1) <= 32) return true; |
|
|
|
if (++i >= s.length) return false; |
|
|
|
if (s.charCodeAt(2) <= 32) return true; |
|
|
|
if (++i >= s.length) return false; |
|
|
|
if (s.charCodeAt(3) <= 32) return true; |
|
|
|
if (++i >= s.length) return false; |
|
|
|
if (s.charCodeAt(4) <= 32) return true; |
|
|
|
if (++i >= s.length) return false; |
|
|
|
if (s.charCodeAt(5) <= 32) return true; |
|
|
|
++i; |
|
|
|
for (; i < s.length; ++i) |
|
|
|
if (s.charCodeAt(i) <= 32) return true; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
function ClientRequest(options, cb) { |
|
|
|
var self = this; |
|
|
|
OutgoingMessage.call(self); |
|
|
@ -45,14 +73,20 @@ function ClientRequest(options, cb) { |
|
|
|
if (self.agent && self.agent.protocol) |
|
|
|
expectedProtocol = self.agent.protocol; |
|
|
|
|
|
|
|
if (options.path && /[\u0000-\u0020]/.test(options.path)) { |
|
|
|
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
|
|
|
|
// with an additional rule for ignoring percentage-escaped characters
|
|
|
|
// but that's a) hard to capture in a regular expression that performs
|
|
|
|
// well, and b) possibly too restrictive for real-world usage.
|
|
|
|
// Restrict the filter to control characters and spaces.
|
|
|
|
throw new TypeError('Request path contains unescaped characters'); |
|
|
|
} else if (protocol !== expectedProtocol) { |
|
|
|
var path; |
|
|
|
if (options.path) { |
|
|
|
path = '' + options.path; |
|
|
|
var invalidPath; |
|
|
|
if (path.length <= 39) { // Determined experimentally in V8 5.4
|
|
|
|
invalidPath = isInvalidPath(path); |
|
|
|
} else { |
|
|
|
invalidPath = /[\u0000-\u0020]/.test(path); |
|
|
|
} |
|
|
|
if (invalidPath) |
|
|
|
throw new TypeError('Request path contains unescaped characters'); |
|
|
|
} |
|
|
|
|
|
|
|
if (protocol !== expectedProtocol) { |
|
|
|
throw new Error('Protocol "' + protocol + '" not supported. ' + |
|
|
|
'Expected "' + expectedProtocol + '"'); |
|
|
|
} |
|
|
|