Skip to content

Commit

Permalink
Allow explicitly disabling tunneling for proxied https destinations
Browse files Browse the repository at this point in the history
Before, tunneling would default to false for http destinations and be
forced to true for https destinations.

Now, allow specifying `tunnel : false` to perform a regular GET request
to HTTPS destinations.  This is insecure, so make a note accordingly.

Supersedes request#1344 and fixes request#1293.
  • Loading branch information
nylen committed Jan 25, 2015
1 parent 0e22b30 commit e69a48e
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 15 deletions.
16 changes: 12 additions & 4 deletions README.md
Expand Up @@ -157,6 +157,10 @@ or other features, it is generally simpler to go with a
straightforward HTTP proxy in this case. However, if you would like
to force a tunneling proxy, you may set the `tunnel` option to `true`.

You can also make a standard proxied `http` request by explicitly setting
`tunnel : false`, but **note that this will allow the proxy to see the traffic
to/from the destination server**.

If you are using a tunneling proxy, you may set the
`proxyHeaderWhiteList` to share certain headers with the proxy.

Expand Down Expand Up @@ -609,10 +613,14 @@ The first argument can be either a `url` or an `options` object. The only requir
* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.
* `localAddress` - Local interface to bind for network connections.
* `gzip` - If `true`, add an `Accept-Encoding` header to request compressed content encodings from the server (if not already present) and decode supported content encodings in the response. **Note:** Automatic decoding of the response content is performed on the body data returned through `request` (both through the `request` stream and passed to the callback function) but is not performed on the `response` stream (available from the `response` event) which is the unmodified `http.IncomingMessage` object which may contain compressed data. See example below.
* `tunnel` - If `true`, then *always* use a tunneling proxy. If
`false` (default), then tunneling will only be used if the
destination is `https`, or if a previous request in the redirect
chain used a tunneling proxy.
* `tunnel` - controls the behavior of
[HTTP `CONNECT` tunneling](https://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_tunneling)
as follows:
* `undefined` (default) - `true` if the destination is `https` or a previous
request in the redirect chain used a tunneling proxy, `false` otherwise
* `true` - always tunnel to the destination by making a `CONNECT` request to
the proxy
* `false` - request the destination as a `GET` request.
* `proxyHeaderWhiteList` - A whitelist of headers to send to a
tunneling proxy.
* `proxyHeaderExclusiveList` - A whitelist of headers to send
Expand Down
13 changes: 6 additions & 7 deletions request.js
Expand Up @@ -209,7 +209,6 @@ function rfc3986 (str) {
}

function Request (options) {
// if tunnel property of options was not given default to false
// if given the method property in options, set property explicitMethod to true

// extend the Request instance with any non-reserved properties
Expand All @@ -228,13 +227,9 @@ function Request (options) {

self.readable = true
self.writable = true
if (typeof options.tunnel === 'undefined') {
options.tunnel = false
}
if (options.method) {
self.explicitMethod = true
}
self.canTunnel = options.tunnel !== false && tunnel
self.init(options)
}

Expand Down Expand Up @@ -263,7 +258,7 @@ Request.prototype.setupTunnel = function () {
return false
}

if (!self.tunnel && self.uri.protocol !== 'https:') {
if (!self.tunnel) {
return false
}

Expand Down Expand Up @@ -384,7 +379,11 @@ Request.prototype.init = function (options) {
}

// Pass in `tunnel:true` to *always* tunnel through proxies
self.tunnel = !!options.tunnel
if (typeof options.tunnel === 'undefined') {
self.tunnel = (self.uri.protocol === 'https:')
} else {
self.tunnel = !!options.tunnel
}
if (self.proxy) {
self.setupTunnel()
}
Expand Down
11 changes: 7 additions & 4 deletions tests/test-tunnel.js
Expand Up @@ -19,6 +19,8 @@ var events = []
cert : path.resolve(__dirname, 'ssl/ca/localhost.crt')
}

// this is needed for 'https over http, tunnel=false' test
// from https://github.com/coolaj86/node-ssl-root-cas/blob/v1.1.9-beta/ssl-root-cas.js#L4267-L4281
var httpsOpts = https.globalAgent.options
httpsOpts.ca = httpsOpts.ca || []
httpsOpts.ca.push(ca)
Expand Down Expand Up @@ -181,9 +183,9 @@ runTest('https over http, tunnel=true', {
runTest('https over http, tunnel=false', {
url : ss.url,
proxy : s.url,
tunnel : false // currently has no effect
tunnel : false
}, [
'http connect to localhost:' + ss.port,
'http proxy to https',
'https response',
'200 https ok'
])
Expand Down Expand Up @@ -213,9 +215,10 @@ runTest('https over https, tunnel=true', {
runTest('https over https, tunnel=false', {
url : ss.url,
proxy : ss.url,
tunnel : false // currently has no effect
tunnel : false,
pool : false // must disable pooling here or Node.js hangs
}, [
'https connect to localhost:' + ss.port,
'https proxy to https',
'https response',
'200 https ok'
])
Expand Down

0 comments on commit e69a48e

Please sign in to comment.