Switch to new repository
diff --git a/node_modules/http-proxy/lib/http-proxy.js b/node_modules/http-proxy/lib/http-proxy.js
new file mode 100644
index 0000000..7dab7a4
--- /dev/null
+++ b/node_modules/http-proxy/lib/http-proxy.js
@@ -0,0 +1,66 @@
+ // Use explicit /index.js to help browserify negociation in require '/lib/http-proxy' (!)
+var ProxyServer = require('./http-proxy/index.js').Server;
+
+
+/**
+ * Creates the proxy server.
+ *
+ * Examples:
+ *
+ * httpProxy.createProxyServer({ .. }, 8000)
+ * // => '{ web: [Function], ws: [Function] ... }'
+ *
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @return {Object} Proxy Proxy object with handlers for `ws` and `web` requests
+ *
+ * @api public
+ */
+
+
+function createProxyServer(options) {
+ /*
+ * `options` is needed and it must have the following layout:
+ *
+ * {
+ * target : <url string to be parsed with the url module>
+ * forward: <url string to be parsed with the url module>
+ * agent : <object to be passed to http(s).request>
+ * ssl : <object to be passed to https.createServer()>
+ * ws : <true/false, if you want to proxy websockets>
+ * xfwd : <true/false, adds x-forward headers>
+ * secure : <true/false, verify SSL certificate>
+ * toProxy: <true/false, explicitly specify if we are proxying to another proxy>
+ * prependPath: <true/false, Default: true - specify whether you want to prepend the target's path to the proxy path>
+ * ignorePath: <true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request>
+ * localAddress : <Local interface string to bind for outgoing connections>
+ * changeOrigin: <true/false, Default: false - changes the origin of the host header to the target URL>
+ * preserveHeaderKeyCase: <true/false, Default: false - specify whether you want to keep letter case of response header key >
+ * auth : Basic authentication i.e. 'user:password' to compute an Authorization header.
+ * hostRewrite: rewrites the location hostname on (301/302/307/308) redirects, Default: null.
+ * autoRewrite: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
+ * protocolRewrite: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
+ * }
+ *
+ * NOTE: `options.ws` and `options.ssl` are optional.
+ * `options.target and `options.forward` cannot be
+ * both missing
+ * }
+ */
+
+ return new ProxyServer(options);
+}
+
+
+ProxyServer.createProxyServer = createProxyServer;
+ProxyServer.createServer = createProxyServer;
+ProxyServer.createProxy = createProxyServer;
+
+
+
+
+/**
+ * Export the proxy "Server" as the main export.
+ */
+module.exports = ProxyServer;
+
diff --git a/node_modules/http-proxy/lib/http-proxy/common.js b/node_modules/http-proxy/lib/http-proxy/common.js
new file mode 100644
index 0000000..6513e81
--- /dev/null
+++ b/node_modules/http-proxy/lib/http-proxy/common.js
@@ -0,0 +1,248 @@
+var common = exports,
+ url = require('url'),
+ extend = require('util')._extend,
+ required = require('requires-port');
+
+var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i,
+ isSSL = /^https|wss/;
+
+/**
+ * Simple Regex for testing if protocol is https
+ */
+common.isSSL = isSSL;
+/**
+ * Copies the right headers from `options` and `req` to
+ * `outgoing` which is then used to fire the proxied
+ * request.
+ *
+ * Examples:
+ *
+ * common.setupOutgoing(outgoing, options, req)
+ * // => { host: ..., hostname: ...}
+ *
+ * @param {Object} Outgoing Base object to be filled with required properties
+ * @param {Object} Options Config object passed to the proxy
+ * @param {ClientRequest} Req Request Object
+ * @param {String} Forward String to select forward or target
+ *
+ * @return {Object} Outgoing Object with all required properties set
+ *
+ * @api private
+ */
+
+common.setupOutgoing = function(outgoing, options, req, forward) {
+ outgoing.port = options[forward || 'target'].port ||
+ (isSSL.test(options[forward || 'target'].protocol) ? 443 : 80);
+
+ ['host', 'hostname', 'socketPath', 'pfx', 'key',
+ 'passphrase', 'cert', 'ca', 'ciphers', 'secureProtocol'].forEach(
+ function(e) { outgoing[e] = options[forward || 'target'][e]; }
+ );
+
+ outgoing.method = options.method || req.method;
+ outgoing.headers = extend({}, req.headers);
+
+ if (options.headers){
+ extend(outgoing.headers, options.headers);
+ }
+
+ if (options.auth) {
+ outgoing.auth = options.auth;
+ }
+
+ if (options.ca) {
+ outgoing.ca = options.ca;
+ }
+
+ if (isSSL.test(options[forward || 'target'].protocol)) {
+ outgoing.rejectUnauthorized = (typeof options.secure === "undefined") ? true : options.secure;
+ }
+
+
+ outgoing.agent = options.agent || false;
+ outgoing.localAddress = options.localAddress;
+
+ //
+ // Remark: If we are false and not upgrading, set the connection: close. This is the right thing to do
+ // as node core doesn't handle this COMPLETELY properly yet.
+ //
+ if (!outgoing.agent) {
+ outgoing.headers = outgoing.headers || {};
+ if (typeof outgoing.headers.connection !== 'string'
+ || !upgradeHeader.test(outgoing.headers.connection)
+ ) { outgoing.headers.connection = 'close'; }
+ }
+
+
+ // the final path is target path + relative path requested by user:
+ var target = options[forward || 'target'];
+ var targetPath = target && options.prependPath !== false
+ ? (target.path || '')
+ : '';
+
+ //
+ // Remark: Can we somehow not use url.parse as a perf optimization?
+ //
+ var outgoingPath = !options.toProxy
+ ? (url.parse(req.url).path || '')
+ : req.url;
+
+ //
+ // Remark: ignorePath will just straight up ignore whatever the request's
+ // path is. This can be labeled as FOOT-GUN material if you do not know what
+ // you are doing and are using conflicting options.
+ //
+ outgoingPath = !options.ignorePath ? outgoingPath : '';
+
+ outgoing.path = common.urlJoin(targetPath, outgoingPath);
+
+ if (options.changeOrigin) {
+ outgoing.headers.host =
+ required(outgoing.port, options[forward || 'target'].protocol) && !hasPort(outgoing.host)
+ ? outgoing.host + ':' + outgoing.port
+ : outgoing.host;
+ }
+ return outgoing;
+};
+
+/**
+ * Set the proper configuration for sockets,
+ * set no delay and set keep alive, also set
+ * the timeout to 0.
+ *
+ * Examples:
+ *
+ * common.setupSocket(socket)
+ * // => Socket
+ *
+ * @param {Socket} Socket instance to setup
+ *
+ * @return {Socket} Return the configured socket.
+ *
+ * @api private
+ */
+
+common.setupSocket = function(socket) {
+ socket.setTimeout(0);
+ socket.setNoDelay(true);
+
+ socket.setKeepAlive(true, 0);
+
+ return socket;
+};
+
+/**
+ * Get the port number from the host. Or guess it based on the connection type.
+ *
+ * @param {Request} req Incoming HTTP request.
+ *
+ * @return {String} The port number.
+ *
+ * @api private
+ */
+common.getPort = function(req) {
+ var res = req.headers.host ? req.headers.host.match(/:(\d+)/) : '';
+
+ return res ?
+ res[1] :
+ common.hasEncryptedConnection(req) ? '443' : '80';
+};
+
+/**
+ * Check if the request has an encrypted connection.
+ *
+ * @param {Request} req Incoming HTTP request.
+ *
+ * @return {Boolean} Whether the connection is encrypted or not.
+ *
+ * @api private
+ */
+common.hasEncryptedConnection = function(req) {
+ return Boolean(req.connection.encrypted || req.connection.pair);
+};
+
+/**
+ * OS-agnostic join (doesn't break on URLs like path.join does on Windows)>
+ *
+ * @return {String} The generated path.
+ *
+ * @api private
+ */
+
+common.urlJoin = function() {
+ //
+ // We do not want to mess with the query string. All we want to touch is the path.
+ //
+ var args = Array.prototype.slice.call(arguments),
+ lastIndex = args.length - 1,
+ last = args[lastIndex],
+ lastSegs = last.split('?'),
+ retSegs;
+
+ args[lastIndex] = lastSegs.shift();
+
+ //
+ // Join all strings, but remove empty strings so we don't get extra slashes from
+ // joining e.g. ['', 'am']
+ //
+ retSegs = [
+ args.filter(Boolean).join('/')
+ .replace(/\/+/g, '/')
+ .replace('http:/', 'http://')
+ .replace('https:/', 'https://')
+ ];
+
+ // Only join the query string if it exists so we don't have trailing a '?'
+ // on every request
+
+ // Handle case where there could be multiple ? in the URL.
+ retSegs.push.apply(retSegs, lastSegs);
+
+ return retSegs.join('?')
+};
+
+/**
+ * Rewrites or removes the domain of a cookie header
+ *
+ * @param {String|Array} Header
+ * @param {Object} Config, mapping of domain to rewritten domain.
+ * '*' key to match any domain, null value to remove the domain.
+ *
+ * @api private
+ */
+common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) {
+ if (Array.isArray(header)) {
+ return header.map(function (headerElement) {
+ return rewriteCookieProperty(headerElement, config, property);
+ });
+ }
+ return header.replace(new RegExp("(;\\s*" + property + "=)([^;]+)", 'i'), function(match, prefix, previousValue) {
+ var newValue;
+ if (previousValue in config) {
+ newValue = config[previousValue];
+ } else if ('*' in config) {
+ newValue = config['*'];
+ } else {
+ //no match, return previous value
+ return match;
+ }
+ if (newValue) {
+ //replace value
+ return prefix + newValue;
+ } else {
+ //remove value
+ return '';
+ }
+ });
+};
+
+/**
+ * Check the host and see if it potentially has a port in it (keep it simple)
+ *
+ * @returns {Boolean} Whether we have one or not
+ *
+ * @api private
+ */
+function hasPort(host) {
+ return !!~host.indexOf(':');
+};
diff --git a/node_modules/http-proxy/lib/http-proxy/index.js b/node_modules/http-proxy/lib/http-proxy/index.js
new file mode 100644
index 0000000..977a4b3
--- /dev/null
+++ b/node_modules/http-proxy/lib/http-proxy/index.js
@@ -0,0 +1,185 @@
+var httpProxy = module.exports,
+ extend = require('util')._extend,
+ parse_url = require('url').parse,
+ EE3 = require('eventemitter3'),
+ http = require('http'),
+ https = require('https'),
+ web = require('./passes/web-incoming'),
+ ws = require('./passes/ws-incoming');
+
+httpProxy.Server = ProxyServer;
+
+/**
+ * Returns a function that creates the loader for
+ * either `ws` or `web`'s passes.
+ *
+ * Examples:
+ *
+ * httpProxy.createRightProxy('ws')
+ * // => [Function]
+ *
+ * @param {String} Type Either 'ws' or 'web'
+ *
+ * @return {Function} Loader Function that when called returns an iterator for the right passes
+ *
+ * @api private
+ */
+
+function createRightProxy(type) {
+
+ return function(options) {
+ return function(req, res /*, [head], [opts] */) {
+ var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
+ args = [].slice.call(arguments),
+ cntr = args.length - 1,
+ head, cbl;
+
+ /* optional args parse begin */
+ if(typeof args[cntr] === 'function') {
+ cbl = args[cntr];
+
+ cntr--;
+ }
+
+ var requestOptions = options;
+ if(
+ !(args[cntr] instanceof Buffer) &&
+ args[cntr] !== res
+ ) {
+ //Copy global options
+ requestOptions = extend({}, options);
+ //Overwrite with request options
+ extend(requestOptions, args[cntr]);
+
+ cntr--;
+ }
+
+ if(args[cntr] instanceof Buffer) {
+ head = args[cntr];
+ }
+
+ /* optional args parse end */
+
+ ['target', 'forward'].forEach(function(e) {
+ if (typeof requestOptions[e] === 'string')
+ requestOptions[e] = parse_url(requestOptions[e]);
+ });
+
+ if (!requestOptions.target && !requestOptions.forward) {
+ return this.emit('error', new Error('Must provide a proper URL as target'));
+ }
+
+ for(var i=0; i < passes.length; i++) {
+ /**
+ * Call of passes functions
+ * pass(req, res, options, head)
+ *
+ * In WebSockets case the `res` variable
+ * refer to the connection socket
+ * pass(req, socket, options, head)
+ */
+ if(passes[i](req, res, requestOptions, head, this, cbl)) { // passes can return a truthy value to halt the loop
+ break;
+ }
+ }
+ };
+ };
+}
+httpProxy.createRightProxy = createRightProxy;
+
+function ProxyServer(options) {
+ EE3.call(this);
+
+ options = options || {};
+ options.prependPath = options.prependPath === false ? false : true;
+
+ this.web = this.proxyRequest = createRightProxy('web')(options);
+ this.ws = this.proxyWebsocketRequest = createRightProxy('ws')(options);
+ this.options = options;
+
+ this.webPasses = Object.keys(web).map(function(pass) {
+ return web[pass];
+ });
+
+ this.wsPasses = Object.keys(ws).map(function(pass) {
+ return ws[pass];
+ });
+
+ this.on('error', this.onError, this);
+
+}
+
+require('util').inherits(ProxyServer, EE3);
+
+ProxyServer.prototype.onError = function (err) {
+ //
+ // Remark: Replicate node core behavior using EE3
+ // so we force people to handle their own errors
+ //
+ if(this.listeners('error').length === 1) {
+ throw err;
+ }
+};
+
+ProxyServer.prototype.listen = function(port, hostname) {
+ var self = this,
+ closure = function(req, res) { self.web(req, res); };
+
+ this._server = this.options.ssl ?
+ https.createServer(this.options.ssl, closure) :
+ http.createServer(closure);
+
+ if(this.options.ws) {
+ this._server.on('upgrade', function(req, socket, head) { self.ws(req, socket, head); });
+ }
+
+ this._server.listen(port, hostname);
+
+ return this;
+};
+
+ProxyServer.prototype.close = function(callback) {
+ var self = this;
+ if (this._server) {
+ this._server.close(done);
+ }
+
+ // Wrap callback to nullify server after all open connections are closed.
+ function done() {
+ self._server = null;
+ if (callback) {
+ callback.apply(null, arguments);
+ }
+ };
+};
+
+ProxyServer.prototype.before = function(type, passName, callback) {
+ if (type !== 'ws' && type !== 'web') {
+ throw new Error('type must be `web` or `ws`');
+ }
+ var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
+ i = false;
+
+ passes.forEach(function(v, idx) {
+ if(v.name === passName) i = idx;
+ })
+
+ if(i === false) throw new Error('No such pass');
+
+ passes.splice(i, 0, callback);
+};
+ProxyServer.prototype.after = function(type, passName, callback) {
+ if (type !== 'ws' && type !== 'web') {
+ throw new Error('type must be `web` or `ws`');
+ }
+ var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
+ i = false;
+
+ passes.forEach(function(v, idx) {
+ if(v.name === passName) i = idx;
+ })
+
+ if(i === false) throw new Error('No such pass');
+
+ passes.splice(i++, 0, callback);
+};
diff --git a/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js b/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js
new file mode 100644
index 0000000..995a0db
--- /dev/null
+++ b/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js
@@ -0,0 +1,192 @@
+var httpNative = require('http'),
+ httpsNative = require('https'),
+ web_o = require('./web-outgoing'),
+ common = require('../common'),
+ followRedirects = require('follow-redirects');
+
+web_o = Object.keys(web_o).map(function(pass) {
+ return web_o[pass];
+});
+
+var nativeAgents = { http: httpNative, https: httpsNative };
+
+/*!
+ * Array of passes.
+ *
+ * A `pass` is just a function that is executed on `req, res, options`
+ * so that you can easily add new checks while still keeping the base
+ * flexible.
+ */
+
+
+module.exports = {
+
+ /**
+ * Sets `content-length` to '0' if request is of DELETE type.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @api private
+ */
+
+ deleteLength: function deleteLength(req, res, options) {
+ if((req.method === 'DELETE' || req.method === 'OPTIONS')
+ && !req.headers['content-length']) {
+ req.headers['content-length'] = '0';
+ delete req.headers['transfer-encoding'];
+ }
+ },
+
+ /**
+ * Sets timeout in request socket if it was specified in options.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @api private
+ */
+
+ timeout: function timeout(req, res, options) {
+ if(options.timeout) {
+ req.socket.setTimeout(options.timeout);
+ }
+ },
+
+ /**
+ * Sets `x-forwarded-*` headers if specified in config.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @api private
+ */
+
+ XHeaders: function XHeaders(req, res, options) {
+ if(!options.xfwd) return;
+
+ var encrypted = req.isSpdy || common.hasEncryptedConnection(req);
+ var values = {
+ for : req.connection.remoteAddress || req.socket.remoteAddress,
+ port : common.getPort(req),
+ proto: encrypted ? 'https' : 'http'
+ };
+
+ ['for', 'port', 'proto'].forEach(function(header) {
+ req.headers['x-forwarded-' + header] =
+ (req.headers['x-forwarded-' + header] || '') +
+ (req.headers['x-forwarded-' + header] ? ',' : '') +
+ values[header];
+ });
+
+ req.headers['x-forwarded-host'] = req.headers['host'] || '';
+ },
+
+ /**
+ * Does the actual proxying. If `forward` is enabled fires up
+ * a ForwardStream, same happens for ProxyStream. The request
+ * just dies otherwise.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @api private
+ */
+
+ stream: function stream(req, res, options, _, server, clb) {
+
+ // And we begin!
+ server.emit('start', req, res, options.target || options.forward);
+
+ var agents = options.followRedirects ? followRedirects : nativeAgents;
+ var http = agents.http;
+ var https = agents.https;
+
+ if(options.forward) {
+ // If forward enable, so just pipe the request
+ var forwardReq = (options.forward.protocol === 'https:' ? https : http).request(
+ common.setupOutgoing(options.ssl || {}, options, req, 'forward')
+ );
+
+ // error handler (e.g. ECONNRESET, ECONNREFUSED)
+ // Handle errors on incoming request as well as it makes sense to
+ var forwardError = createErrorHandler(forwardReq, options.forward);
+ req.on('error', forwardError);
+ forwardReq.on('error', forwardError);
+
+ (options.buffer || req).pipe(forwardReq);
+ if(!options.target) { return res.end(); }
+ }
+
+ // Request initalization
+ var proxyReq = (options.target.protocol === 'https:' ? https : http).request(
+ common.setupOutgoing(options.ssl || {}, options, req)
+ );
+
+ // Enable developers to modify the proxyReq before headers are sent
+ proxyReq.on('socket', function(socket) {
+ if(server) { server.emit('proxyReq', proxyReq, req, res, options); }
+ });
+
+ // allow outgoing socket to timeout so that we could
+ // show an error page at the initial request
+ if(options.proxyTimeout) {
+ proxyReq.setTimeout(options.proxyTimeout, function() {
+ proxyReq.abort();
+ });
+ }
+
+ // Ensure we abort proxy if request is aborted
+ req.on('aborted', function () {
+ proxyReq.abort();
+ });
+
+ // handle errors in proxy and incoming request, just like for forward proxy
+ var proxyError = createErrorHandler(proxyReq, options.target);
+ req.on('error', proxyError);
+ proxyReq.on('error', proxyError);
+
+ function createErrorHandler(proxyReq, url) {
+ return function proxyError(err) {
+ if (req.socket.destroyed && err.code === 'ECONNRESET') {
+ server.emit('econnreset', err, req, res, url);
+ return proxyReq.abort();
+ }
+
+ if (clb) {
+ clb(err, req, res, url);
+ } else {
+ server.emit('error', err, req, res, url);
+ }
+ }
+ }
+
+ (options.buffer || req).pipe(proxyReq);
+
+ proxyReq.on('response', function(proxyRes) {
+ if(server) { server.emit('proxyRes', proxyRes, req, res); }
+
+ if(!res.headersSent && !options.selfHandleResponse) {
+ for(var i=0; i < web_o.length; i++) {
+ if(web_o[i](req, res, proxyRes, options)) { break; }
+ }
+ }
+
+ if (!res.finished) {
+ // Allow us to listen when the proxy has completed
+ proxyRes.on('end', function () {
+ if (server) server.emit('end', req, res, proxyRes);
+ });
+ // We pipe to the response unless its expected to be handled by the user
+ if (!options.selfHandleResponse) proxyRes.pipe(res);
+ } else {
+ if (server) server.emit('end', req, res, proxyRes);
+ }
+ });
+ }
+
+};
diff --git a/node_modules/http-proxy/lib/http-proxy/passes/web-outgoing.js b/node_modules/http-proxy/lib/http-proxy/passes/web-outgoing.js
new file mode 100644
index 0000000..46352f6
--- /dev/null
+++ b/node_modules/http-proxy/lib/http-proxy/passes/web-outgoing.js
@@ -0,0 +1,147 @@
+var url = require('url'),
+ common = require('../common');
+
+
+var redirectRegex = /^201|30(1|2|7|8)$/;
+
+/*!
+ * Array of passes.
+ *
+ * A `pass` is just a function that is executed on `req, res, options`
+ * so that you can easily add new checks while still keeping the base
+ * flexible.
+ */
+
+module.exports = { // <--
+
+ /**
+ * If is a HTTP 1.0 request, remove chunk headers
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {proxyResponse} Res Response object from the proxy request
+ *
+ * @api private
+ */
+ removeChunked: function removeChunked(req, res, proxyRes) {
+ if (req.httpVersion === '1.0') {
+ delete proxyRes.headers['transfer-encoding'];
+ }
+ },
+
+ /**
+ * If is a HTTP 1.0 request, set the correct connection header
+ * or if connection header not present, then use `keep-alive`
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {proxyResponse} Res Response object from the proxy request
+ *
+ * @api private
+ */
+ setConnection: function setConnection(req, res, proxyRes) {
+ if (req.httpVersion === '1.0') {
+ proxyRes.headers.connection = req.headers.connection || 'close';
+ } else if (req.httpVersion !== '2.0' && !proxyRes.headers.connection) {
+ proxyRes.headers.connection = req.headers.connection || 'keep-alive';
+ }
+ },
+
+ setRedirectHostRewrite: function setRedirectHostRewrite(req, res, proxyRes, options) {
+ if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite)
+ && proxyRes.headers['location']
+ && redirectRegex.test(proxyRes.statusCode)) {
+ var target = url.parse(options.target);
+ var u = url.parse(proxyRes.headers['location']);
+
+ // make sure the redirected host matches the target host before rewriting
+ if (target.host != u.host) {
+ return;
+ }
+
+ if (options.hostRewrite) {
+ u.host = options.hostRewrite;
+ } else if (options.autoRewrite) {
+ u.host = req.headers['host'];
+ }
+ if (options.protocolRewrite) {
+ u.protocol = options.protocolRewrite;
+ }
+
+ proxyRes.headers['location'] = u.format();
+ }
+ },
+ /**
+ * Copy headers from proxyResponse to response
+ * set each header in response object.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {proxyResponse} Res Response object from the proxy request
+ * @param {Object} Options options.cookieDomainRewrite: Config to rewrite cookie domain
+ *
+ * @api private
+ */
+ writeHeaders: function writeHeaders(req, res, proxyRes, options) {
+ var rewriteCookieDomainConfig = options.cookieDomainRewrite,
+ rewriteCookiePathConfig = options.cookiePathRewrite,
+ preserveHeaderKeyCase = options.preserveHeaderKeyCase,
+ rawHeaderKeyMap,
+ setHeader = function(key, header) {
+ if (header == undefined) return;
+ if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') {
+ header = common.rewriteCookieProperty(header, rewriteCookieDomainConfig, 'domain');
+ }
+ if (rewriteCookiePathConfig && key.toLowerCase() === 'set-cookie') {
+ header = common.rewriteCookieProperty(header, rewriteCookiePathConfig, 'path');
+ }
+ res.setHeader(String(key).trim(), header);
+ };
+
+ if (typeof rewriteCookieDomainConfig === 'string') { //also test for ''
+ rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig };
+ }
+
+ if (typeof rewriteCookiePathConfig === 'string') { //also test for ''
+ rewriteCookiePathConfig = { '*': rewriteCookiePathConfig };
+ }
+
+ // message.rawHeaders is added in: v0.11.6
+ // https://nodejs.org/api/http.html#http_message_rawheaders
+ if (preserveHeaderKeyCase && proxyRes.rawHeaders != undefined) {
+ rawHeaderKeyMap = {};
+ for (var i = 0; i < proxyRes.rawHeaders.length; i += 2) {
+ var key = proxyRes.rawHeaders[i];
+ rawHeaderKeyMap[key.toLowerCase()] = key;
+ }
+ }
+
+ Object.keys(proxyRes.headers).forEach(function(key) {
+ var header = proxyRes.headers[key];
+ if (preserveHeaderKeyCase && rawHeaderKeyMap) {
+ key = rawHeaderKeyMap[key] || key;
+ }
+ setHeader(key, header);
+ });
+ },
+
+ /**
+ * Set the statusCode from the proxyResponse
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {IncomingMessage} Res Response object
+ * @param {proxyResponse} Res Response object from the proxy request
+ *
+ * @api private
+ */
+ writeStatusCode: function writeStatusCode(req, res, proxyRes) {
+ // From Node.js docs: response.writeHead(statusCode[, statusMessage][, headers])
+ if(proxyRes.statusMessage) {
+ res.statusCode = proxyRes.statusCode;
+ res.statusMessage = proxyRes.statusMessage;
+ } else {
+ res.statusCode = proxyRes.statusCode;
+ }
+ }
+
+};
diff --git a/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.js b/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.js
new file mode 100644
index 0000000..270f23f
--- /dev/null
+++ b/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.js
@@ -0,0 +1,162 @@
+var http = require('http'),
+ https = require('https'),
+ common = require('../common');
+
+/*!
+ * Array of passes.
+ *
+ * A `pass` is just a function that is executed on `req, socket, options`
+ * so that you can easily add new checks while still keeping the base
+ * flexible.
+ */
+
+/*
+ * Websockets Passes
+ *
+ */
+
+
+module.exports = {
+ /**
+ * WebSocket requests must have the `GET` method and
+ * the `upgrade:websocket` header
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {Socket} Websocket
+ *
+ * @api private
+ */
+
+ checkMethodAndHeader : function checkMethodAndHeader(req, socket) {
+ if (req.method !== 'GET' || !req.headers.upgrade) {
+ socket.destroy();
+ return true;
+ }
+
+ if (req.headers.upgrade.toLowerCase() !== 'websocket') {
+ socket.destroy();
+ return true;
+ }
+ },
+
+ /**
+ * Sets `x-forwarded-*` headers if specified in config.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {Socket} Websocket
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @api private
+ */
+
+ XHeaders : function XHeaders(req, socket, options) {
+ if(!options.xfwd) return;
+
+ var values = {
+ for : req.connection.remoteAddress || req.socket.remoteAddress,
+ port : common.getPort(req),
+ proto: common.hasEncryptedConnection(req) ? 'wss' : 'ws'
+ };
+
+ ['for', 'port', 'proto'].forEach(function(header) {
+ req.headers['x-forwarded-' + header] =
+ (req.headers['x-forwarded-' + header] || '') +
+ (req.headers['x-forwarded-' + header] ? ',' : '') +
+ values[header];
+ });
+ },
+
+ /**
+ * Does the actual proxying. Make the request and upgrade it
+ * send the Switching Protocols request and pipe the sockets.
+ *
+ * @param {ClientRequest} Req Request object
+ * @param {Socket} Websocket
+ * @param {Object} Options Config object passed to the proxy
+ *
+ * @api private
+ */
+ stream : function stream(req, socket, options, head, server, clb) {
+
+ var createHttpHeader = function(line, headers) {
+ return Object.keys(headers).reduce(function (head, key) {
+ var value = headers[key];
+
+ if (!Array.isArray(value)) {
+ head.push(key + ': ' + value);
+ return head;
+ }
+
+ for (var i = 0; i < value.length; i++) {
+ head.push(key + ': ' + value[i]);
+ }
+ return head;
+ }, [line])
+ .join('\r\n') + '\r\n\r\n';
+ }
+
+ common.setupSocket(socket);
+
+ if (head && head.length) socket.unshift(head);
+
+
+ var proxyReq = (common.isSSL.test(options.target.protocol) ? https : http).request(
+ common.setupOutgoing(options.ssl || {}, options, req)
+ );
+
+ // Enable developers to modify the proxyReq before headers are sent
+ if (server) { server.emit('proxyReqWs', proxyReq, req, socket, options, head); }
+
+ // Error Handler
+ proxyReq.on('error', onOutgoingError);
+ proxyReq.on('response', function (res) {
+ // if upgrade event isn't going to happen, close the socket
+ if (!res.upgrade) {
+ socket.write(createHttpHeader('HTTP/' + res.httpVersion + ' ' + res.statusCode + ' ' + res.statusMessage, res.headers));
+ res.pipe(socket);
+ }
+ });
+
+ proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) {
+ proxySocket.on('error', onOutgoingError);
+
+ // Allow us to listen when the websocket has completed
+ proxySocket.on('end', function () {
+ server.emit('close', proxyRes, proxySocket, proxyHead);
+ });
+
+ // The pipe below will end proxySocket if socket closes cleanly, but not
+ // if it errors (eg, vanishes from the net and starts returning
+ // EHOSTUNREACH). We need to do that explicitly.
+ socket.on('error', function () {
+ proxySocket.end();
+ });
+
+ common.setupSocket(proxySocket);
+
+ if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);
+
+ //
+ // Remark: Handle writing the headers to the socket when switching protocols
+ // Also handles when a header is an array
+ //
+ socket.write(createHttpHeader('HTTP/1.1 101 Switching Protocols', proxyRes.headers));
+
+ proxySocket.pipe(socket).pipe(proxySocket);
+
+ server.emit('open', proxySocket);
+ server.emit('proxySocket', proxySocket); //DEPRECATED.
+ });
+
+ return proxyReq.end(); // XXX: CHECK IF THIS IS THIS CORRECT
+
+ function onOutgoingError(err) {
+ if (clb) {
+ clb(err, req, socket);
+ } else {
+ server.emit('error', err, req, socket);
+ }
+ socket.end();
+ }
+ }
+};