mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
[minor] Style updates and whitespace cleaning for consistency
This commit is contained in:
parent
8eaec35074
commit
f0917a3f97
@ -1,11 +1,34 @@
|
|||||||
#!/usr/local/bin/node
|
/*
|
||||||
|
body-decoder.js: Example of body-decoder middleware with node-http-proxy
|
||||||
|
|
||||||
|
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
var httpProxy = require('http-proxy'),
|
var httpProxy = require('http-proxy'),
|
||||||
http = require('http'),
|
http = require('http'),
|
||||||
util = require('util'),
|
util = require('util'),
|
||||||
colors = require('colors');
|
colors = require('colors');
|
||||||
|
|
||||||
|
|
||||||
exports.bodyMod = function () {
|
exports.bodyMod = function () {
|
||||||
console.log('middleware has been started.'.green);
|
console.log('middleware has been started.'.green);
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
@ -16,16 +39,22 @@ exports.bodyMod = function () {
|
|||||||
console.log('ON DATA')
|
console.log('ON DATA')
|
||||||
total += data;
|
total += data;
|
||||||
});
|
});
|
||||||
|
|
||||||
req.on('end', function () {
|
req.on('end', function () {
|
||||||
console.log('ON END')
|
console.log('ON END')
|
||||||
console.log(total);
|
console.log(total);
|
||||||
|
//
|
||||||
// This line, uncommented, hangs forever.
|
// This line, uncommented, hangs forever.
|
||||||
// proxy.proxyRequest(req, res, { port: 9000, host: 'localhost' });
|
// proxy.proxyRequest(req, res, { port: 9000, host: 'localhost' });
|
||||||
// The following also hangs forever.
|
// The following also hangs forever.
|
||||||
// next.proxyRequest(req, res, { port: 9000, host: 'localhost' });
|
// next.proxyRequest(req, res, { port: 9000, host: 'localhost' });
|
||||||
})
|
//
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
// The following fires just fine.
|
// The following fires just fine.
|
||||||
//proxy.proxyRequest(req, res, { port: 9000, host: 'localhost' });
|
//proxy.proxyRequest(req, res, { port: 9000, host: 'localhost' });
|
||||||
|
//
|
||||||
console.log('request proxied...'.blue);
|
console.log('request proxied...'.blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
gzip-middleware.js: Basic example of middleware in node-http-proxy
|
gzip-middleware.js: Basic example of `connect-gzip` middleware in node-http-proxy
|
||||||
|
|
||||||
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, Marak Squires, & Dominic Tarr.
|
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, Marak Squires, & Dominic Tarr.
|
||||||
|
|
||||||
@ -32,7 +32,6 @@ var util = require('util'),
|
|||||||
//
|
//
|
||||||
// Basic Http Proxy Server
|
// Basic Http Proxy Server
|
||||||
//
|
//
|
||||||
|
|
||||||
httpProxy.createServer(
|
httpProxy.createServer(
|
||||||
require('connect-gzip').gzip({ matchType: /.?/ }),
|
require('connect-gzip').gzip({ matchType: /.?/ }),
|
||||||
9000, 'localhost'
|
9000, 'localhost'
|
||||||
@ -41,12 +40,11 @@ httpProxy.createServer(
|
|||||||
//
|
//
|
||||||
// Target Http Server
|
// Target Http Server
|
||||||
//
|
//
|
||||||
http.createServer(
|
http.createServer(function (req, res) {
|
||||||
function (req, res) {
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
res.end();
|
||||||
res.end();
|
}).listen(9000);
|
||||||
}).listen(9000);
|
|
||||||
|
|
||||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
||||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);
|
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);
|
||||||
|
|||||||
@ -1,3 +1,29 @@
|
|||||||
|
/*
|
||||||
|
url-middleware.js: Example of a simple url routing middleware for node-http-proxy
|
||||||
|
|
||||||
|
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
var util = require('util'),
|
var util = require('util'),
|
||||||
colors = require('colors'),
|
colors = require('colors'),
|
||||||
http = require('http'),
|
http = require('http'),
|
||||||
@ -10,13 +36,18 @@ var util = require('util'),
|
|||||||
//
|
//
|
||||||
|
|
||||||
function matcher (url, dest) {
|
function matcher (url, dest) {
|
||||||
|
//
|
||||||
// First, turn the URL into a regex.
|
// First, turn the URL into a regex.
|
||||||
// NOTE: Turning user input directly into a Regular Expression is NOT SAFE.
|
// NOTE: Turning user input directly into a Regular Expression is NOT SAFE.
|
||||||
|
//
|
||||||
var r = new RegExp(url.replace(/\//, '\\/'));
|
var r = new RegExp(url.replace(/\//, '\\/'));
|
||||||
|
|
||||||
|
//
|
||||||
// This next block of code may look a little confusing.
|
// This next block of code may look a little confusing.
|
||||||
// It returns a closure (anonymous function) for each URL to be matched,
|
// It returns a closure (anonymous function) for each URL to be matched,
|
||||||
// storing them in an array - on each request, if the URL matches one that has
|
// storing them in an array - on each request, if the URL matches one that has
|
||||||
// a function stored for it, the function will be called.
|
// a function stored for it, the function will be called.
|
||||||
|
//
|
||||||
return function (url) {
|
return function (url) {
|
||||||
var m = r(url)
|
var m = r(url)
|
||||||
if (!m) {
|
if (!m) {
|
||||||
@ -24,7 +55,10 @@ function matcher (url, dest) {
|
|||||||
}
|
}
|
||||||
var path = url.slice(m[0].length);
|
var path = url.slice(m[0].length);
|
||||||
console.log('proxy:', url, '->', dest);
|
console.log('proxy:', url, '->', dest);
|
||||||
return {url: path, dest: dest};
|
return {
|
||||||
|
url: path,
|
||||||
|
dest: dest
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,26 +95,29 @@ exports.urls = function (urls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// Now we set up our proxy.
|
// Now we set up our proxy.
|
||||||
|
//
|
||||||
httpProxy.createServer(
|
httpProxy.createServer(
|
||||||
|
//
|
||||||
// This is where our middlewares go, with any options desired - in this case,
|
// This is where our middlewares go, with any options desired - in this case,
|
||||||
// the list of routes/URLs and their destinations.
|
// the list of routes/URLs and their destinations.
|
||||||
|
//
|
||||||
exports.urls({
|
exports.urls({
|
||||||
'/hello': { port: 9000, host: 'localhost' },
|
'/hello': { port: 9000, host: 'localhost' },
|
||||||
'/charlie': { port: 80, host: 'charlieistheman.com' },
|
'/charlie': { port: 80, host: 'charlieistheman.com' },
|
||||||
'/google': { port: 80, host: 'google.com' }
|
'/google': { port: 80, host: 'google.com' }
|
||||||
})
|
});
|
||||||
).listen(8000);
|
).listen(8000);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Target Http Server (to listen for requests on 'localhost')
|
// Target Http Server (to listen for requests on 'localhost')
|
||||||
//
|
//
|
||||||
http.createServer(
|
http.createServer(function (req, res) {
|
||||||
function (req, res) {
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
res.end();
|
||||||
res.end();
|
}).listen(9000);
|
||||||
}).listen(9000);
|
|
||||||
|
|
||||||
// And finally, some colored startup output.
|
// And finally, some colored startup output.
|
||||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
||||||
|
|||||||
@ -47,6 +47,7 @@ var server = http.createServer(function (req, res) {
|
|||||||
res.writeHead(200);
|
res.writeHead(200);
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen(8080);
|
server.listen(8080);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
node-http-proxy.js: http proxy for node.js
|
node-http-proxy.js: http proxy for node.js
|
||||||
|
|
||||||
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Marak Squires, Fedor Indutny
|
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Marak Squires, Fedor Indutny
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
@ -51,16 +51,16 @@ var _agents = {};
|
|||||||
//
|
//
|
||||||
function _getAgent (host, port, secure) {
|
function _getAgent (host, port, secure) {
|
||||||
var Agent, id = [host, port].join(':');
|
var Agent, id = [host, port].join(':');
|
||||||
|
|
||||||
if (!port) {
|
if (!port) {
|
||||||
port = secure ? 443 : 80;
|
port = secure ? 443 : 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_agents[id]) {
|
if (!_agents[id]) {
|
||||||
Agent = secure ? https.Agent : http.Agent;
|
Agent = secure ? https.Agent : http.Agent;
|
||||||
|
|
||||||
_agents[id] = new Agent({
|
_agents[id] = new Agent({
|
||||||
host: host,
|
host: host,
|
||||||
port: port,
|
port: port,
|
||||||
maxSockets: maxSockets
|
maxSockets: maxSockets
|
||||||
});
|
});
|
||||||
@ -70,17 +70,17 @@ function _getAgent (host, port, secure) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function _getProtocol (secure, outgoing)
|
// ### function _getProtocol (secure, outgoing)
|
||||||
// #### @secure {Object|boolean} Settings for `https`
|
// #### @secure {Object|boolean} Settings for `https`
|
||||||
// #### @outgoing {Object} Outgoing request options
|
// #### @outgoing {Object} Outgoing request options
|
||||||
// Returns the appropriate protocol based on the settings in
|
// Returns the appropriate protocol based on the settings in
|
||||||
// `secure`. If the protocol is `https` this function will update
|
// `secure`. If the protocol is `https` this function will update
|
||||||
// the options in `outgoing` as appropriate by adding `ca`, `key`,
|
// the options in `outgoing` as appropriate by adding `ca`, `key`,
|
||||||
// and `cert` if they exist in `secure`.
|
// and `cert` if they exist in `secure`.
|
||||||
//
|
//
|
||||||
function _getProtocol (secure, outgoing) {
|
function _getProtocol (secure, outgoing) {
|
||||||
var protocol = secure ? https : http;
|
var protocol = secure ? https : http;
|
||||||
|
|
||||||
if (typeof secure === 'object') {
|
if (typeof secure === 'object') {
|
||||||
outgoing = outgoing || {};
|
outgoing = outgoing || {};
|
||||||
['ca', 'cert', 'key'].forEach(function (prop) {
|
['ca', 'cert', 'key'].forEach(function (prop) {
|
||||||
@ -89,7 +89,7 @@ function _getProtocol (secure, outgoing) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return protocol;
|
return protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,25 +117,27 @@ exports.setMaxSockets = function (value) {
|
|||||||
// stack
|
// stack
|
||||||
// adapted from https://github.com/creationix/stack
|
// adapted from https://github.com/creationix/stack
|
||||||
//
|
//
|
||||||
|
|
||||||
function stack (middlewares, proxy) {
|
function stack (middlewares, proxy) {
|
||||||
var handle;
|
var handle;
|
||||||
middlewares.reverse().forEach(function (layer) {
|
middlewares.reverse().forEach(function (layer) {
|
||||||
|
|
||||||
var child = handle;
|
var child = handle;
|
||||||
handle = function (req, res) {
|
handle = function (req, res) {
|
||||||
var next = function (err) {
|
var next = function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
//TODO: figure out where to send errors.
|
//
|
||||||
//return error(req, res, err);
|
// TODO: figure out where to send errors.
|
||||||
}
|
// return error(req, res, err);
|
||||||
child(req, res);
|
//
|
||||||
}
|
}
|
||||||
|
child(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
next.__proto__ = proxy;
|
next.__proto__ = proxy;
|
||||||
layer(req, res, next);
|
layer(req, res, next);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,48 +154,60 @@ function stack (middlewares, proxy) {
|
|||||||
// * `httpPRoxy.createServer(function (req, res, proxy) { ... })`
|
// * `httpPRoxy.createServer(function (req, res, proxy) { ... })`
|
||||||
//
|
//
|
||||||
exports.createServer = function () {
|
exports.createServer = function () {
|
||||||
var args = Array.prototype.slice.call(arguments),
|
var args = Array.prototype.slice.call(arguments),
|
||||||
callback,
|
callback, forward,
|
||||||
options = {}, port, host, forward, silent, proxy, server, middleware = [];
|
port, host,
|
||||||
|
proxy, server,
|
||||||
|
options = {},
|
||||||
|
middleware = [],
|
||||||
|
silent;
|
||||||
|
|
||||||
args.forEach(function (arg) {
|
args.forEach(function (arg) {
|
||||||
|
|
||||||
switch (typeof arg) {
|
switch (typeof arg) {
|
||||||
case 'string': host = arg; break;
|
case 'string': host = arg; break;
|
||||||
case 'number': port = arg; break;
|
case 'number': port = arg; break;
|
||||||
case 'function': middleware.push(arg); break;
|
case 'function': middleware.push(arg); break;
|
||||||
case 'object': options = arg; break;
|
case 'object': options = arg; break;
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var proxy = new HttpProxy(options);
|
var proxy = new HttpProxy(options);
|
||||||
|
|
||||||
if (port && host) {
|
if (port && host) {
|
||||||
//
|
//
|
||||||
// If we have a target host and port for the request
|
// If we have a target host and port for the request
|
||||||
// then proxy to the specified location.
|
// then proxy to the specified location.
|
||||||
//
|
//
|
||||||
handler = function (req, res) {
|
handler = function (req, res) {
|
||||||
proxy.proxyRequest(req, res, {
|
proxy.proxyRequest(req, res, {
|
||||||
port: port,
|
port: port,
|
||||||
host: host
|
host: host
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if(middleware.length) middleware.push(handler)
|
|
||||||
}
|
|
||||||
else if (proxy.proxyTable) {
|
|
||||||
//
|
|
||||||
// If the proxy is configured with a ProxyTable
|
|
||||||
// instance then use that before failing.
|
|
||||||
//
|
|
||||||
handler = function (req, res) {
|
|
||||||
proxy.proxyRequest(req, res);
|
|
||||||
}
|
|
||||||
if(middleware.length) middleware.push(handler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(middleware.length) handler = stack(middleware, proxy);
|
if (middleware.length) {
|
||||||
|
middleware.push(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (proxy.proxyTable) {
|
||||||
|
//
|
||||||
|
// If the proxy is configured with a ProxyTable
|
||||||
|
// instance then use that before failing.
|
||||||
|
//
|
||||||
|
handler = function (req, res) {
|
||||||
|
proxy.proxyRequest(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (middleware.length) {
|
||||||
|
middleware.push(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (middleware.length) {
|
||||||
|
//handler = callback = middleware.shift()
|
||||||
|
//else if (middleware.length)
|
||||||
|
handler = callback = stack(middleware, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
//
|
//
|
||||||
@ -202,37 +216,36 @@ exports.createServer = function () {
|
|||||||
throw new Error('Cannot proxy without port, host, or router.')
|
throw new Error('Cannot proxy without port, host, or router.')
|
||||||
}
|
}
|
||||||
|
|
||||||
server = options.https
|
server = options.https
|
||||||
? https.createServer(options.https, handler)
|
? https.createServer(options.https, handler)
|
||||||
: http.createServer(handler);
|
: http.createServer(handler);
|
||||||
|
|
||||||
server.on('close', function () {
|
server.on('close', function () {
|
||||||
proxy.close();
|
proxy.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
proxy.on('routes', function (routes) {
|
proxy.on('routes', function (routes) {
|
||||||
server.emit('routes', routes);
|
server.emit('routes', routes);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
// WebSocket support: if callback is empty tunnel
|
// WebSocket support: if callback is empty tunnel
|
||||||
// websocket request automatically
|
// websocket request automatically
|
||||||
server.on('upgrade', function (req, socket, head) {
|
server.on('upgrade', function (req, socket, head) {
|
||||||
// Tunnel websocket requests too
|
// Tunnel websocket requests too
|
||||||
|
|
||||||
proxy.proxyWebSocketRequest(req, socket, head, {
|
proxy.proxyWebSocketRequest(req, socket, head, {
|
||||||
port: port,
|
port: port,
|
||||||
host: host
|
host: host
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set the proxy on the server so it is available
|
// Set the proxy on the server so it is available
|
||||||
// to the consumer of the server
|
// to the consumer of the server
|
||||||
//
|
//
|
||||||
server.proxy = proxy;
|
server.proxy = proxy;
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -253,23 +266,23 @@ exports.createServer = function () {
|
|||||||
// host: 'localhost',
|
// host: 'localhost',
|
||||||
// port: 9001
|
// port: 9001
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
var HttpProxy = exports.HttpProxy = function (options) {
|
var HttpProxy = exports.HttpProxy = function (options) {
|
||||||
events.EventEmitter.call(this);
|
events.EventEmitter.call(this);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup basic proxying options
|
// Setup basic proxying options
|
||||||
//
|
//
|
||||||
this.https = options.https;
|
this.https = options.https;
|
||||||
this.forward = options.forward;
|
this.forward = options.forward;
|
||||||
this.target = options.target || {};
|
this.target = options.target || {};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup additional options for WebSocket proxying. When forcing
|
// Setup additional options for WebSocket proxying. When forcing
|
||||||
// the WebSocket handshake to change the `sec-websocket-location`
|
// the WebSocket handshake to change the `sec-websocket-location`
|
||||||
// and `sec-websocket-origin` headers `options.source` **MUST**
|
// and `sec-websocket-origin` headers `options.source` **MUST**
|
||||||
// be provided or the operation will fail with an `origin mismatch`
|
// be provided or the operation will fail with an `origin mismatch`
|
||||||
@ -277,7 +290,7 @@ var HttpProxy = exports.HttpProxy = function (options) {
|
|||||||
//
|
//
|
||||||
this.source = options.source || { host: 'localhost', port: 8000 };
|
this.source = options.source || { host: 'localhost', port: 8000 };
|
||||||
this.changeOrigin = options.changeOrigin || false;
|
this.changeOrigin = options.changeOrigin || false;
|
||||||
|
|
||||||
if (options.router) {
|
if (options.router) {
|
||||||
this.proxyTable = new ProxyTable(options.router, options.silent, options.hostnameOnly);
|
this.proxyTable = new ProxyTable(options.router, options.silent, options.hostnameOnly);
|
||||||
this.proxyTable.on('routes', function (routes) {
|
this.proxyTable.on('routes', function (routes) {
|
||||||
@ -290,10 +303,10 @@ var HttpProxy = exports.HttpProxy = function (options) {
|
|||||||
util.inherits(HttpProxy, events.EventEmitter);
|
util.inherits(HttpProxy, events.EventEmitter);
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function buffer (obj)
|
// ### function buffer (obj)
|
||||||
// #### @obj {Object} Object to pause events from
|
// #### @obj {Object} Object to pause events from
|
||||||
// Buffer `data` and `end` events from the given `obj`.
|
// Buffer `data` and `end` events from the given `obj`.
|
||||||
// Consumers of HttpProxy performing async tasks
|
// Consumers of HttpProxy performing async tasks
|
||||||
// __must__ utilize this utility, to re-emit data once
|
// __must__ utilize this utility, to re-emit data once
|
||||||
// the async operation has completed, otherwise these
|
// the async operation has completed, otherwise these
|
||||||
// __events will be lost.__
|
// __events will be lost.__
|
||||||
@ -303,9 +316,9 @@ util.inherits(HttpProxy, events.EventEmitter);
|
|||||||
// httpProxy.proxyRequest(req, res, host, port, buffer);
|
// httpProxy.proxyRequest(req, res, host, port, buffer);
|
||||||
// });
|
// });
|
||||||
//
|
//
|
||||||
// __Attribution:__ This approach is based heavily on
|
// __Attribution:__ This approach is based heavily on
|
||||||
// [Connect](https://github.com/senchalabs/connect/blob/master/lib/utils.js#L157).
|
// [Connect](https://github.com/senchalabs/connect/blob/master/lib/utils.js#L157).
|
||||||
// However, this is not a big leap from the implementation in node-http-proxy < 0.4.0.
|
// However, this is not a big leap from the implementation in node-http-proxy < 0.4.0.
|
||||||
// This simply chooses to manage the scope of the events on a new Object literal as opposed to
|
// This simply chooses to manage the scope of the events on a new Object literal as opposed to
|
||||||
// [on the HttpProxy instance](https://github.com/nodejitsu/node-http-proxy/blob/v0.3.1/lib/node-http-proxy.js#L154).
|
// [on the HttpProxy instance](https://github.com/nodejitsu/node-http-proxy/blob/v0.3.1/lib/node-http-proxy.js#L154).
|
||||||
//
|
//
|
||||||
@ -337,10 +350,12 @@ HttpProxy.prototype.buffer = function (obj) {
|
|||||||
//
|
//
|
||||||
// ### function close ()
|
// ### function close ()
|
||||||
// Frees the resources associated with this instance,
|
// Frees the resources associated with this instance,
|
||||||
// if they exist.
|
// if they exist.
|
||||||
//
|
//
|
||||||
HttpProxy.prototype.close = function () {
|
HttpProxy.prototype.close = function () {
|
||||||
if (this.proxyTable) this.proxyTable.close();
|
if (this.proxyTable) {
|
||||||
|
this.proxyTable.close();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -357,18 +372,18 @@ HttpProxy.prototype.close = function () {
|
|||||||
//
|
//
|
||||||
HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
||||||
var self = this, errState = false, location, outgoing, protocol, reverseProxy;
|
var self = this, errState = false, location, outgoing, protocol, reverseProxy;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create an empty options hash if none is passed.
|
// Create an empty options hash if none is passed.
|
||||||
// If default options have been passed to the constructor
|
// If default options have been passed to the constructor
|
||||||
// of this instance, use them by default.
|
// of this instance, use them by default.
|
||||||
//
|
//
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.host = options.host || this.target.host;
|
options.host = options.host || this.target.host;
|
||||||
options.port = options.port || this.target.port;
|
options.port = options.port || this.target.port;
|
||||||
options.enableXForwarded =
|
options.enableXForwarded =
|
||||||
(undefined === options.enableXForwarded ? true : options.enableXForwarded);
|
(undefined === options.enableXForwarded ? true : options.enableXForwarded);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the proxy table for this instance to see if we need
|
// Check the proxy table for this instance to see if we need
|
||||||
// to get the proxy location for the request supplied. We will
|
// to get the proxy location for the request supplied. We will
|
||||||
@ -377,7 +392,7 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
//
|
//
|
||||||
if (this.proxyTable && !options.host) {
|
if (this.proxyTable && !options.host) {
|
||||||
location = this.proxyTable.getProxyLocation(req);
|
location = this.proxyTable.getProxyLocation(req);
|
||||||
|
|
||||||
//
|
//
|
||||||
// If no location is returned from the ProxyTable instance
|
// If no location is returned from the ProxyTable instance
|
||||||
// then respond with `404` since we do not have a valid proxy target.
|
// then respond with `404` since we do not have a valid proxy target.
|
||||||
@ -386,38 +401,38 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
res.writeHead(404);
|
res.writeHead(404);
|
||||||
return res.end();
|
return res.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// When using the ProxyTable in conjunction with an HttpProxy instance
|
// When using the ProxyTable in conjunction with an HttpProxy instance
|
||||||
// only the following arguments are valid:
|
// only the following arguments are valid:
|
||||||
//
|
//
|
||||||
// * `proxy.proxyRequest(req, res, { host: 'localhost' })`: This will be skipped
|
// * `proxy.proxyRequest(req, res, { host: 'localhost' })`: This will be skipped
|
||||||
// * `proxy.proxyRequest(req, res, { buffer: buffer })`: Buffer will get updated appropriately
|
// * `proxy.proxyRequest(req, res, { buffer: buffer })`: Buffer will get updated appropriately
|
||||||
// * `proxy.proxyRequest(req, res)`: Options will be assigned appropriately.
|
// * `proxy.proxyRequest(req, res)`: Options will be assigned appropriately.
|
||||||
//
|
//
|
||||||
options.port = location.port;
|
options.port = location.port;
|
||||||
options.host = location.host;
|
options.host = location.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Add common proxy headers to the request so that they can
|
// Add common proxy headers to the request so that they can
|
||||||
// be availible to the proxy target server:
|
// be availible to the proxy target server:
|
||||||
//
|
//
|
||||||
// * `x-forwarded-for`: IP Address of the original request
|
// * `x-forwarded-for`: IP Address of the original request
|
||||||
// * `x-forwarded-proto`: Protocol of the original request
|
// * `x-forwarded-proto`: Protocol of the original request
|
||||||
// * `x-forwarded-port`: Port of the original request.
|
// * `x-forwarded-port`: Port of the original request.
|
||||||
//
|
//
|
||||||
if (options.enableXForwarded == true) {
|
if (options.enableXForwarded === true) {
|
||||||
req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.connection.socket.remoteAddress;
|
req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.connection.socket.remoteAddress;
|
||||||
req.headers['x-forwarded-port'] = req.connection.remotePort || req.connection.socket.remotePort;
|
req.headers['x-forwarded-port'] = req.connection.remotePort || req.connection.socket.remotePort;
|
||||||
req.headers['x-forwarded-proto'] = res.connection.pair ? 'https' : 'http';
|
req.headers['x-forwarded-proto'] = res.connection.pair ? 'https' : 'http';
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Emit the `start` event indicating that we have begun the proxy operation.
|
// Emit the `start` event indicating that we have begun the proxy operation.
|
||||||
//
|
//
|
||||||
this.emit('start', req, res, options);
|
this.emit('start', req, res, options);
|
||||||
|
|
||||||
//
|
//
|
||||||
// If forwarding is enabled for this instance, foward proxy the
|
// If forwarding is enabled for this instance, foward proxy the
|
||||||
// specified request to the address provided in `this.forward`
|
// specified request to the address provided in `this.forward`
|
||||||
@ -426,16 +441,16 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
this.emit('forward', req, res, this.forward);
|
this.emit('forward', req, res, this.forward);
|
||||||
this._forwardRequest(req);
|
this._forwardRequest(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// #### function proxyError (err)
|
// #### function proxyError (err)
|
||||||
// #### @err {Error} Error contacting the proxy target
|
// #### @err {Error} Error contacting the proxy target
|
||||||
// Short-circuits `res` in the event of any error when
|
// Short-circuits `res` in the event of any error when
|
||||||
// contacting the proxy target at `host` / `port`.
|
// contacting the proxy target at `host` / `port`.
|
||||||
//
|
//
|
||||||
function proxyError(err) {
|
function proxyError(err) {
|
||||||
errState = true;
|
errState = true;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Emit an `error` event, allowing the application to use custom
|
// Emit an `error` event, allowing the application to use custom
|
||||||
// error handling. The error handler should end the response.
|
// error handling. The error handler should end the response.
|
||||||
@ -458,10 +473,10 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
res.write('An error has occurred: ' + JSON.stringify(err));
|
res.write('An error has occurred: ' + JSON.stringify(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.end();
|
res.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
outgoing = {
|
outgoing = {
|
||||||
host: options.host,
|
host: options.host,
|
||||||
port: options.port,
|
port: options.port,
|
||||||
@ -470,12 +485,12 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
path: req.url,
|
path: req.url,
|
||||||
headers: req.headers
|
headers: req.headers
|
||||||
};
|
};
|
||||||
|
|
||||||
protocol = _getProtocol(options.https || this.target.https, outgoing);
|
protocol = _getProtocol(options.https || this.target.https, outgoing);
|
||||||
|
|
||||||
// Open new HTTP request to internal resource with will act as a reverse proxy pass
|
// Open new HTTP request to internal resource with will act as a reverse proxy pass
|
||||||
reverseProxy = protocol.request(outgoing, function (response) {
|
reverseProxy = protocol.request(outgoing, function (response) {
|
||||||
|
|
||||||
// Process the `reverseProxy` `response` when it's received.
|
// Process the `reverseProxy` `response` when it's received.
|
||||||
if (response.headers.connection) {
|
if (response.headers.connection) {
|
||||||
if (req.headers.connection) response.headers.connection = req.headers.connection;
|
if (req.headers.connection) response.headers.connection = req.headers.connection;
|
||||||
@ -507,17 +522,17 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
if (!errState) {
|
if (!errState) {
|
||||||
reverseProxy.removeListener('error', proxyError);
|
reverseProxy.removeListener('error', proxyError);
|
||||||
res.end();
|
res.end();
|
||||||
|
|
||||||
// Emit the `end` event now that we have completed proxying
|
// Emit the `end` event now that we have completed proxying
|
||||||
self.emit('end', req, res);
|
self.emit('end', req, res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle 'error' events from the `reverseProxy`.
|
// Handle 'error' events from the `reverseProxy`.
|
||||||
reverseProxy.once('error', proxyError);
|
reverseProxy.once('error', proxyError);
|
||||||
|
|
||||||
// For each data `chunk` received from the incoming
|
// For each data `chunk` received from the incoming
|
||||||
// `req` write it to the `reverseProxy` request.
|
// `req` write it to the `reverseProxy` request.
|
||||||
req.on('data', function (chunk) {
|
req.on('data', function (chunk) {
|
||||||
if (!errState) {
|
if (!errState) {
|
||||||
@ -526,8 +541,8 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// When the incoming `req` ends, end the corresponding `reverseProxy`
|
// When the incoming `req` ends, end the corresponding `reverseProxy`
|
||||||
// request unless we have entered an error state.
|
// request unless we have entered an error state.
|
||||||
//
|
//
|
||||||
req.on('end', function () {
|
req.on('end', function () {
|
||||||
if (!errState) {
|
if (!errState) {
|
||||||
@ -540,7 +555,7 @@ HttpProxy.prototype.proxyRequest = function (req, res, options) {
|
|||||||
options.buffer.resume();
|
options.buffer.resume();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### @private function _forwardRequest (req)
|
// ### @private function _forwardRequest (req)
|
||||||
// #### @req {ServerRequest} Incoming HTTP Request to proxy.
|
// #### @req {ServerRequest} Incoming HTTP Request to proxy.
|
||||||
@ -552,7 +567,7 @@ HttpProxy.prototype._forwardRequest = function (req) {
|
|||||||
|
|
||||||
port = this.forward.port;
|
port = this.forward.port;
|
||||||
host = this.forward.host;
|
host = this.forward.host;
|
||||||
|
|
||||||
outgoing = {
|
outgoing = {
|
||||||
host: host,
|
host: host,
|
||||||
port: port,
|
port: port,
|
||||||
@ -561,13 +576,13 @@ HttpProxy.prototype._forwardRequest = function (req) {
|
|||||||
path: req.url,
|
path: req.url,
|
||||||
headers: req.headers
|
headers: req.headers
|
||||||
};
|
};
|
||||||
|
|
||||||
// Force the `connection` header to be 'close' until
|
// Force the `connection` header to be 'close' until
|
||||||
// node.js core re-implements 'keep-alive'.
|
// node.js core re-implements 'keep-alive'.
|
||||||
outgoing.headers['connection'] = 'close';
|
outgoing.headers['connection'] = 'close';
|
||||||
|
|
||||||
protocol = _getProtocol(this.forward.https, outgoing);
|
protocol = _getProtocol(this.forward.https, outgoing);
|
||||||
|
|
||||||
// Open new HTTP request to internal resource with will act as a reverse proxy pass
|
// Open new HTTP request to internal resource with will act as a reverse proxy pass
|
||||||
forwardProxy = protocol.request(outgoing, function (response) {
|
forwardProxy = protocol.request(outgoing, function (response) {
|
||||||
//
|
//
|
||||||
@ -575,10 +590,10 @@ HttpProxy.prototype._forwardRequest = function (req) {
|
|||||||
// Remark (indexzero): We will eventually emit a 'forward' event here for performance tuning.
|
// Remark (indexzero): We will eventually emit a 'forward' event here for performance tuning.
|
||||||
//
|
//
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a listener for the connection timeout event.
|
// Add a listener for the connection timeout event.
|
||||||
//
|
//
|
||||||
// Remark: Ignoring this error in the event
|
// Remark: Ignoring this error in the event
|
||||||
// forward target doesn't exist.
|
// forward target doesn't exist.
|
||||||
//
|
//
|
||||||
forwardProxy.once('error', function (err) { });
|
forwardProxy.once('error', function (err) { });
|
||||||
@ -596,7 +611,7 @@ HttpProxy.prototype._forwardRequest = function (req) {
|
|||||||
|
|
||||||
//
|
//
|
||||||
// ### function proxyWebSocketRequest (req, socket, head, options)
|
// ### function proxyWebSocketRequest (req, socket, head, options)
|
||||||
// #### @req {ServerRequest} Websocket request to proxy.
|
// #### @req {ServerRequest} Websocket request to proxy.
|
||||||
// #### @socket {net.Socket} Socket for the underlying HTTP request
|
// #### @socket {net.Socket} Socket for the underlying HTTP request
|
||||||
// #### @head {string} Headers for the Websocket request.
|
// #### @head {string} Headers for the Websocket request.
|
||||||
// #### @options {Object} Options to use when proxying this request.
|
// #### @options {Object} Options to use when proxying this request.
|
||||||
@ -607,28 +622,30 @@ HttpProxy.prototype._forwardRequest = function (req) {
|
|||||||
// options.https {Object|boolean} Settings for https.
|
// options.https {Object|boolean} Settings for https.
|
||||||
//
|
//
|
||||||
HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options) {
|
HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options) {
|
||||||
var self = this,
|
var self = this,
|
||||||
listeners = {},
|
listeners = {},
|
||||||
errState = false,
|
errState = false,
|
||||||
CRLF = '\r\n',
|
CRLF = '\r\n',
|
||||||
outgoing;
|
outgoing;
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.host = options.host || this.target.host;
|
options.host = options.host || this.target.host;
|
||||||
options.port = options.port || this.target.port;
|
options.port = options.port || this.target.port;
|
||||||
|
|
||||||
if (this.proxyTable && !options.host) {
|
if (this.proxyTable && !options.host) {
|
||||||
location = this.proxyTable.getProxyLocation(req);
|
location = this.proxyTable.getProxyLocation(req);
|
||||||
|
|
||||||
if (!location) {
|
if (!location) {
|
||||||
res.writeHead(404);
|
res.writeHead(404);
|
||||||
return res.end();
|
return res.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
options.port = location.port;
|
options.port = location.port;
|
||||||
options.host = location.host;
|
options.host = location.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// WebSocket requests must have the `GET` method and
|
// WebSocket requests must have the `GET` method and
|
||||||
// the `upgrade:websocket` header
|
// the `upgrade:websocket` header
|
||||||
//
|
//
|
||||||
if (req.method !== 'GET' || req.headers.upgrade.toLowerCase() !== 'websocket') {
|
if (req.method !== 'GET' || req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||||
@ -637,7 +654,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
//
|
//
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Helper function for setting appropriate socket values:
|
// Helper function for setting appropriate socket values:
|
||||||
// 1. Turn of all bufferings
|
// 1. Turn of all bufferings
|
||||||
@ -654,14 +671,14 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
else if (socket.pair.cleartext.socket.setKeepAlive) {
|
else if (socket.pair.cleartext.socket.setKeepAlive) {
|
||||||
socket.pair.cleartext.socket.setKeepAlive(true, 0);
|
socket.pair.cleartext.socket.setKeepAlive(true, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
socket.setEncoding('utf8');
|
socket.setEncoding('utf8');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// On `upgrade` from the Agent socket, listen to
|
// On `upgrade` from the Agent socket, listen to
|
||||||
// the appropriate events.
|
// the appropriate events.
|
||||||
//
|
//
|
||||||
function onUpgrade (reverseProxy, proxySocket) {
|
function onUpgrade (reverseProxy, proxySocket) {
|
||||||
@ -670,7 +687,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
socket.end();
|
socket.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Any incoming data on this WebSocket to the proxy target
|
// Any incoming data on this WebSocket to the proxy target
|
||||||
// will be written to the `reverseProxy` socket.
|
// will be written to the `reverseProxy` socket.
|
||||||
@ -680,7 +697,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
try {
|
try {
|
||||||
self.emit('websocket:outgoing', req, socket, head, data);
|
self.emit('websocket:outgoing', req, socket, head, data);
|
||||||
reverseProxy.incoming.socket.write(data);
|
reverseProxy.incoming.socket.write(data);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
reverseProxy.incoming.socket.end();
|
reverseProxy.incoming.socket.end();
|
||||||
proxySocket.end();
|
proxySocket.end();
|
||||||
@ -696,15 +713,15 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
try {
|
try {
|
||||||
self.emit('websocket:incoming', reverseProxy, reverseProxy.incoming, head, data);
|
self.emit('websocket:incoming', reverseProxy, reverseProxy.incoming, head, data);
|
||||||
proxySocket.write(data);
|
proxySocket.write(data);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
proxySocket.end();
|
proxySocket.end();
|
||||||
socket.end();
|
socket.end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// Helper function to detach all event listeners
|
// Helper function to detach all event listeners
|
||||||
// from `reverseProxy` and `proxySocket`.
|
// from `reverseProxy` and `proxySocket`.
|
||||||
//
|
//
|
||||||
function detach() {
|
function detach() {
|
||||||
@ -715,19 +732,19 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the incoming `proxySocket` socket closes, then
|
// If the incoming `proxySocket` socket closes, then
|
||||||
// detach all event listeners.
|
// detach all event listeners.
|
||||||
//
|
//
|
||||||
proxySocket.on('end', listeners.onIncomingClose = function() {
|
proxySocket.on('end', listeners.onIncomingClose = function() {
|
||||||
reverseProxy.incoming.socket.end();
|
reverseProxy.incoming.socket.end();
|
||||||
detach();
|
detach();
|
||||||
|
|
||||||
// Emit the `end` event now that we have completed proxying
|
// Emit the `end` event now that we have completed proxying
|
||||||
self.emit('websocket:end', req, socket, head);
|
self.emit('websocket:end', req, socket, head);
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the `reverseProxy` socket closes, then detach all
|
// If the `reverseProxy` socket closes, then detach all
|
||||||
// event listeners.
|
// event listeners.
|
||||||
//
|
//
|
||||||
reverseProxy.incoming.socket.on('end', listeners.onOutgoingClose = function() {
|
reverseProxy.incoming.socket.on('end', listeners.onOutgoingClose = function() {
|
||||||
@ -738,12 +755,12 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
|
|
||||||
// Setup the incoming client socket.
|
// Setup the incoming client socket.
|
||||||
_socket(socket);
|
_socket(socket);
|
||||||
|
|
||||||
function getPort (port) {
|
function getPort (port) {
|
||||||
port = port || 80;
|
port = port || 80;
|
||||||
return port - 80 === 0 ? '' : ':' + port
|
return port - 80 === 0 ? '' : ':' + port
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the protocol, and host for this request and create an instance
|
// Get the protocol, and host for this request and create an instance
|
||||||
// of `http.Agent` or `https.Agent` from the pool managed by `node-http-proxy`.
|
// of `http.Agent` or `https.Agent` from the pool managed by `node-http-proxy`.
|
||||||
@ -758,7 +775,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
req.headers.host = remoteHost;
|
req.headers.host = remoteHost;
|
||||||
req.headers.origin = protocolName + '://' + remoteHost;
|
req.headers.origin = protocolName + '://' + remoteHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make the outgoing WebSocket request
|
// Make the outgoing WebSocket request
|
||||||
//
|
//
|
||||||
@ -772,7 +789,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
var reverseProxy = agent.appendMessage(outgoing);
|
var reverseProxy = agent.appendMessage(outgoing);
|
||||||
|
|
||||||
//
|
//
|
||||||
// On any errors from the `reverseProxy` emit the
|
// On any errors from the `reverseProxy` emit the
|
||||||
// `webSocketProxyError` and close the appropriate
|
// `webSocketProxyError` and close the appropriate
|
||||||
// connections.
|
// connections.
|
||||||
//
|
//
|
||||||
@ -781,14 +798,14 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
if (self.emit('webSocketProxyError', req, socket, head)) {
|
if (self.emit('webSocketProxyError', req, socket, head)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.end();
|
socket.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Here we set the incoming `req`, `socket` and `head` data to the outgoing
|
// Here we set the incoming `req`, `socket` and `head` data to the outgoing
|
||||||
// request so that we can reuse this data later on in the closure scope
|
// request so that we can reuse this data later on in the closure scope
|
||||||
// available to the `upgrade` event. This bookkeeping is not tracked anywhere
|
// available to the `upgrade` event. This bookkeeping is not tracked anywhere
|
||||||
// in nodejs core and is **very** specific to proxying WebSockets.
|
// in nodejs core and is **very** specific to proxying WebSockets.
|
||||||
//
|
//
|
||||||
reverseProxy.agent = agent;
|
reverseProxy.agent = agent;
|
||||||
@ -797,27 +814,27 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
socket: socket,
|
socket: socket,
|
||||||
head: head
|
head: head
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the agent for this particular `host` and `port` combination
|
// If the agent for this particular `host` and `port` combination
|
||||||
// is not already listening for the `upgrade` event, then do so once.
|
// is not already listening for the `upgrade` event, then do so once.
|
||||||
// This will force us not to disconnect.
|
// This will force us not to disconnect.
|
||||||
//
|
//
|
||||||
// In addition, it's important to note the closure scope here. Since
|
// In addition, it's important to note the closure scope here. Since
|
||||||
// there is no mapping of the
|
// there is no mapping of the
|
||||||
//
|
//
|
||||||
if (!agent._events || agent._events['upgrade'].length === 0) {
|
if (!agent._events || agent._events['upgrade'].length === 0) {
|
||||||
agent.on('upgrade', function (_, remoteSocket, head) {
|
agent.on('upgrade', function (_, remoteSocket, head) {
|
||||||
//
|
//
|
||||||
// Prepare the socket for the reverseProxy request and begin to
|
// Prepare the socket for the reverseProxy request and begin to
|
||||||
// stream data between the two sockets. Here it is important to
|
// stream data between the two sockets. Here it is important to
|
||||||
// note that `remoteSocket._httpMessage === reverseProxy`.
|
// note that `remoteSocket._httpMessage === reverseProxy`.
|
||||||
//
|
//
|
||||||
_socket(remoteSocket, true);
|
_socket(remoteSocket, true);
|
||||||
onUpgrade(remoteSocket._httpMessage, remoteSocket);
|
onUpgrade(remoteSocket._httpMessage, remoteSocket);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the reverseProxy connection has an underlying socket,
|
// If the reverseProxy connection has an underlying socket,
|
||||||
// then execute the WebSocket handshake.
|
// then execute the WebSocket handshake.
|
||||||
@ -826,9 +843,9 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
reverseProxy.socket.on('data', function handshake (data) {
|
reverseProxy.socket.on('data', function handshake (data) {
|
||||||
//
|
//
|
||||||
// Ok, kind of harmfull part of code. Socket.IO sends a hash
|
// Ok, kind of harmfull part of code. Socket.IO sends a hash
|
||||||
// at the end of handshake if protocol === 76, but we need
|
// at the end of handshake if protocol === 76, but we need
|
||||||
// to replace 'host' and 'origin' in response so we split
|
// to replace 'host' and 'origin' in response so we split
|
||||||
// data to printable data and to non-printable. (Non-printable
|
// data to printable data and to non-printable. (Non-printable
|
||||||
// will come after double-CRLF).
|
// will come after double-CRLF).
|
||||||
//
|
//
|
||||||
var sdata = data.toString();
|
var sdata = data.toString();
|
||||||
@ -838,7 +855,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
|
|
||||||
// Get the Non-Printable data
|
// Get the Non-Printable data
|
||||||
data = data.slice(Buffer.byteLength(sdata), data.length);
|
data = data.slice(Buffer.byteLength(sdata), data.length);
|
||||||
|
|
||||||
if (self.https && !self.target.https) {
|
if (self.https && !self.target.https) {
|
||||||
//
|
//
|
||||||
// If the proxy server is running HTTPS but the client is running
|
// If the proxy server is running HTTPS but the client is running
|
||||||
@ -850,12 +867,12 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
try {
|
try {
|
||||||
//
|
//
|
||||||
// Write the printable and non-printable data to the socket
|
// Write the printable and non-printable data to the socket
|
||||||
// from the original incoming request.
|
// from the original incoming request.
|
||||||
//
|
//
|
||||||
self.emit('websocket:handshake', req, socket, head, sdata, data);
|
self.emit('websocket:handshake', req, socket, head, sdata, data);
|
||||||
socket.write(sdata);
|
socket.write(sdata);
|
||||||
socket.write(data);
|
socket.write(data);
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
proxyError(ex)
|
proxyError(ex)
|
||||||
}
|
}
|
||||||
@ -867,7 +884,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
reverseProxy.socket.removeListener('data', handshake);
|
reverseProxy.socket.removeListener('data', handshake);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseProxy.on('error', proxyError);
|
reverseProxy.on('error', proxyError);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -875,11 +892,11 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
|
|||||||
// Attempt to write the upgrade-head to the reverseProxy request.
|
// Attempt to write the upgrade-head to the reverseProxy request.
|
||||||
//
|
//
|
||||||
reverseProxy.write(head);
|
reverseProxy.write(head);
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
proxyError(ex);
|
proxyError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we have been passed buffered data, resume it.
|
// If we have been passed buffered data, resume it.
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user