/vendor/assets/bower_components/angular-count-to/scripts/node_modules/karma/node_modules/http-proxy/lib/node-http-proxy.js
JavaScript | 394 lines | 183 code | 41 blank | 170 comment | 31 complexity | bf5c1248e17d60f03e8163165ad70441 MD5 | raw file
- /*
- node-http-proxy.js: http proxy for node.js
- Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Marak Squires, Fedor Indutny
- 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'),
- http = require('http'),
- https = require('https'),
- events = require('events'),
- maxSockets = 100;
- //
- // Expose version information through `pkginfo`.
- //
- require('pkginfo')(module, 'version');
- //
- // ### Export the relevant objects exposed by `node-http-proxy`
- //
- var HttpProxy = exports.HttpProxy = require('./node-http-proxy/http-proxy').HttpProxy,
- ProxyTable = exports.ProxyTable = require('./node-http-proxy/proxy-table').ProxyTable,
- RoutingProxy = exports.RoutingProxy = require('./node-http-proxy/routing-proxy').RoutingProxy;
- //
- // ### function createServer ([port, host, options, handler])
- // #### @port {number} **Optional** Port to use on the proxy target host.
- // #### @host {string} **Optional** Host of the proxy target.
- // #### @options {Object} **Optional** Options for the HttpProxy instance used
- // #### @handler {function} **Optional** Request handler for the server
- // Returns a server that manages an instance of HttpProxy. Flexible arguments allow for:
- //
- // * `httpProxy.createServer(9000, 'localhost')`
- // * `httpProxy.createServer(9000, 'localhost', options)
- // * `httpPRoxy.createServer(function (req, res, proxy) { ... })`
- //
- exports.createServer = function () {
- var args = Array.prototype.slice.call(arguments),
- handlers = [],
- callback,
- options = {},
- message,
- handler,
- server,
- proxy,
- host,
- port;
- //
- // Liberally parse arguments of the form:
- //
- // httpProxy.createServer('localhost', 9000, callback);
- // httpProxy.createServer({ host: 'localhost', port: 9000 }, callback);
- // **NEED MORE HERE!!!**
- //
- args.forEach(function (arg) {
- arg = Number(arg) || arg;
- switch (typeof arg) {
- case 'string': host = arg; break;
- case 'number': port = arg; break;
- case 'object': options = arg || {}; break;
- case 'function': callback = arg; handlers.push(callback); break;
- };
- });
- //
- // Helper function to create intelligent error message(s)
- // for the very liberal arguments parsing performed by
- // `require('http-proxy').createServer()`.
- //
- function validArguments() {
- var conditions = {
- 'port and host': function () {
- return port && host;
- },
- 'options.target or options.router': function () {
- return options && (options.router ||
- (options.target && options.target.host && options.target.port));
- },
- 'or proxy handlers': function () {
- return handlers && handlers.length;
- }
- }
- var missing = Object.keys(conditions).filter(function (name) {
- return !conditions[name]();
- });
- if (missing.length === 3) {
- message = 'Cannot proxy without ' + missing.join(', ');
- return false;
- }
- return true;
- }
- if (!validArguments()) {
- //
- // If `host`, `port` and `options` are all not passed (with valid
- // options) then this server is improperly configured.
- //
- throw new Error(message);
- return;
- }
- //
- // Hoist up any explicit `host` or `port` arguments
- // that have been passed in to the options we will
- // pass to the `httpProxy.HttpProxy` constructor.
- //
- options.target = options.target || {};
- options.target.port = options.target.port || port;
- options.target.host = options.target.host || host;
- if (options.target && options.target.host && options.target.port) {
- //
- // If an explicit `host` and `port` combination has been passed
- // to `.createServer()` then instantiate a hot-path optimized
- // `HttpProxy` object and add the "proxy" middleware layer.
- //
- proxy = new HttpProxy(options);
- handlers.push(function (req, res) {
- proxy.proxyRequest(req, res);
- });
- }
- else {
- //
- // If no explicit `host` or `port` combination has been passed then
- // we have to assume that this is a "go-anywhere" Proxy (i.e. a `RoutingProxy`).
- //
- proxy = new RoutingProxy(options);
- if (options.router) {
- //
- // If a routing table has been supplied than we assume
- // the user intends us to add the "proxy" middleware layer
- // for them
- //
- handlers.push(function (req, res) {
- proxy.proxyRequest(req, res);
- });
- proxy.on('routes', function (routes) {
- server.emit('routes', routes);
- });
- }
- }
- //
- // Create the `http[s].Server` instance which will use
- // an instance of `httpProxy.HttpProxy`.
- //
- handler = handlers.length > 1
- ? exports.stack(handlers, proxy)
- : function (req, res) { handlers[0](req, res, proxy) };
- server = options.https
- ? https.createServer(options.https, handler)
- : http.createServer(handler);
- server.on('close', function () {
- proxy.close();
- });
- if (!callback) {
- //
- // If an explicit callback has not been supplied then
- // automagically proxy the request using the `HttpProxy`
- // instance we have created.
- //
- server.on('upgrade', function (req, socket, head) {
- proxy.proxyWebSocketRequest(req, socket, head);
- });
- }
- //
- // Set the proxy on the server so it is available
- // to the consumer of the server
- //
- server.proxy = proxy;
- return server;
- };
- //
- // ### function buffer (obj)
- // #### @obj {Object} Object to pause events from
- // Buffer `data` and `end` events from the given `obj`.
- // Consumers of HttpProxy performing async tasks
- // __must__ utilize this utility, to re-emit data once
- // the async operation has completed, otherwise these
- // __events will be lost.__
- //
- // var buffer = httpProxy.buffer(req);
- // fs.readFile(path, function () {
- // httpProxy.proxyRequest(req, res, host, port, buffer);
- // });
- //
- // __Attribution:__ This approach is based heavily on
- // [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.
- // 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).
- //
- exports.buffer = function (obj) {
- var events = [],
- onData,
- onEnd;
- obj.on('data', onData = function (data, encoding) {
- events.push(['data', data, encoding]);
- });
- obj.on('end', onEnd = function (data, encoding) {
- events.push(['end', data, encoding]);
- });
- return {
- end: function () {
- obj.removeListener('data', onData);
- obj.removeListener('end', onEnd);
- },
- destroy: function () {
- this.end();
- this.resume = function () {
- console.error("Cannot resume buffer after destroying it.");
- };
- onData = onEnd = events = obj = null;
- },
- resume: function () {
- this.end();
- for (var i = 0, len = events.length; i < len; ++i) {
- obj.emit.apply(obj, events[i]);
- }
- }
- };
- };
- //
- // ### function getMaxSockets ()
- // Returns the maximum number of sockets
- // allowed on __every__ outgoing request
- // made by __all__ instances of `HttpProxy`
- //
- exports.getMaxSockets = function () {
- return maxSockets;
- };
- //
- // ### function setMaxSockets ()
- // Sets the maximum number of sockets
- // allowed on __every__ outgoing request
- // made by __all__ instances of `HttpProxy`
- //
- exports.setMaxSockets = function (value) {
- maxSockets = value;
- };
- //
- // ### function stack (middlewares, proxy)
- // #### @middlewares {Array} Array of functions to stack.
- // #### @proxy {HttpProxy|RoutingProxy} Proxy instance to
- // Iteratively build up a single handler to the `http.Server`
- // `request` event (i.e. `function (req, res)`) by wrapping
- // each middleware `layer` into a `child` middleware which
- // is in invoked by the parent (i.e. predecessor in the Array).
- //
- // adapted from https://github.com/creationix/stack
- //
- exports.stack = function stack (middlewares, proxy) {
- var handle;
- middlewares.reverse().forEach(function (layer) {
- var child = handle;
- handle = function (req, res) {
- var next = function (err) {
- if (err) {
- if (res._headerSent) {
- res.destroy();
- }
- else {
- res.statusCode = 500;
- res.setHeader('Content-Type', 'text/plain');
- res.end('Internal Server Error');
- }
- console.error('Error in middleware(s): %s', err.stack);
- return;
- }
- if (child) {
- child(req, res);
- }
- };
- //
- // Set the prototype of the `next` function to the instance
- // of the `proxy` so that in can be used interchangably from
- // a `connect` style callback and a true `HttpProxy` object.
- //
- // e.g. `function (req, res, next)` vs. `function (req, res, proxy)`
- //
- next.__proto__ = proxy;
- layer(req, res, next);
- };
- });
- return handle;
- };
- //
- // ### function _getAgent (host, port, secure)
- // #### @options {Object} Options to use when creating the agent.
- //
- // {
- // host: 'localhost',
- // port: 9000,
- // https: true,
- // maxSockets: 100
- // }
- //
- // Createsan agent from the `http` or `https` module
- // and sets the `maxSockets` property appropriately.
- //
- exports._getAgent = function _getAgent (options) {
- if (!options || !options.host) {
- throw new Error('`options.host` is required to create an Agent.');
- }
- if (!options.port) {
- options.port = options.https ? 443 : 80;
- }
- var Agent = options.https ? https.Agent : http.Agent,
- agent;
- // require('http-proxy').setMaxSockets() should override http's default
- // configuration value (which is pretty low).
- options.maxSockets = options.maxSockets || maxSockets;
- agent = new Agent(options);
- return agent;
- }
- //
- // ### function _getProtocol (options)
- // #### @options {Object} Options for the proxy target.
- // Returns the appropriate node.js core protocol module (i.e. `http` or `https`)
- // based on the `options` supplied.
- //
- exports._getProtocol = function _getProtocol (options) {
- return options.https ? https : http;
- };
- //
- // ### function _getBase (options)
- // #### @options {Object} Options for the proxy target.
- // Returns the relevate base object to create on outgoing proxy request.
- // If `options.https` are supplied, this function respond with an object
- // containing the relevant `ca`, `key`, and `cert` properties.
- //
- exports._getBase = function _getBase (options) {
- var result = function () {};
- if (options.https && typeof options.https === 'object') {
- ['ca', 'cert', 'key'].forEach(function (key) {
- if (options.https[key]) {
- result.prototype[key] = options.https[key];
- }
- });
- }
- return result;
- };