all files / http-proxy-middleware/lib/ index.js

96.77% Statements 60/62
77.27% Branches 17/22
100% Functions 8/8
96.77% Lines 60/62
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125       41× 41× 41×     41× 41×   41×     41×     41×       41×   41×     38×   38× 34× 34×       38×                               38× 38×         38× 38×     38×         38×       38×   38×             38× 11×   11×                  
var _              = require('lodash');
var httpProxy      = require('http-proxy');
var configFactory  = require('./config-factory');
var handlers       = require('./handlers');
var contextMatcher = require('./context-matcher');
var PathRewriter   = require('./path-rewriter');
var Router         = require('./router');
var logger         = require('./logger').getInstance();
var getArrow       = require('./logger').getArrow;
 
module.exports = HttpProxyMiddleware;
 
function HttpProxyMiddleware(context, opts) {
    // https://github.com/chimurai/http-proxy-middleware/issues/57
    var wsUpgradeDebounced  = _.debounce(handleUpgrade);
    var config              = configFactory.createConfig(context, opts);
    var proxyOptions        = config.options;
 
    // create proxy
    var proxy = httpProxy.createProxyServer({});
    logger.info('[HPM] Proxy created:', config.context, ' -> ', proxyOptions.target);
 
    var pathRewriter = PathRewriter.create(proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
 
    // attach handler to http-proxy events
    handlers.init(proxy, proxyOptions);
 
    // log errors for debug purpose
    proxy.on('error', logError);
 
    // https://github.com/chimurai/http-proxy-middleware/issues/19
    // expose function to upgrade externally
    middleware.upgrade = wsUpgradeDebounced;
 
    return middleware;
 
    function middleware(req, res, next) {
        // https://github.com/chimurai/http-proxy-middleware/issues/17
        req.url = req.originalUrl;
 
        if (contextMatcher.match(config.context, req.url, req)) {
            var activeProxyOptions = prepareProxyRequest(req);
            proxy.web(req, res, activeProxyOptions);
        } else {
            next();
        }
 
        if (proxyOptions.ws === true) {
            catchUpgradeRequest(req.connection.server);
        }
    }
 
    function catchUpgradeRequest(server) {
        server.on('upgrade', wsUpgradeDebounced);
    }
 
    function handleUpgrade(req, socket, head) {
        Eif (contextMatcher.match(config.context, req.url, req)) {
            var activeProxyOptions = prepareProxyRequest(req);
            proxy.ws(req, socket, head, activeProxyOptions);
            logger.info('[HPM] Upgrading to WebSocket');
        }
    }
 
    /**
     * Apply option.router and option.pathRewrite
     * Order matters:
          Router uses original path for routing;
          NOT the modified path, after it has been rewritten by pathRewrite
     */
    function prepareProxyRequest(req) {
        // store uri before it gets rewritten for logging
        var originalPath = req.url;
        var newProxyOptions = _.cloneDeep(proxyOptions);
 
        // Apply in order:
        // 1. option.router
        // 2. option.pathRewrite
        __applyRouter(req, newProxyOptions);
        __applyPathRewrite(req, pathRewriter);
 
        // debug logging for both http(s) and websockets
        Iif (proxyOptions.logLevel === 'debug') {
            var arrow = getArrow(originalPath, req.url, proxyOptions.target, newProxyOptions.target);
            logger.debug('[HPM] %s %s %s %s', req.method, originalPath, arrow, newProxyOptions.target);
        }
 
        return newProxyOptions;
    }
 
    // Modify option.target when router present.
    function __applyRouter(req, options) {
        var newTarget;
 
        if (options.router) {
            newTarget = Router.getTarget(req, options);
 
            if (newTarget) {
                logger.debug('[HPM] Router new target: %s -> "%s"', options.target, newTarget);
                options.target = newTarget;
            }
        }
    }
 
    // rewrite path
    function __applyPathRewrite(req, pathRewriter) {
        if (pathRewriter) {
            var path = pathRewriter(req.url, req);
 
            if (path) {
                req.url =  path;
            } else {
                logger.info('[HPM] pathRewrite: No rewritten path found. (%s)', req.url);
            }
        }
    }
 
    function logError(err, req, res) {
        var hostname = (req.hostname || req.host) || (req.headers && req.headers.host); // (node0.10 || node 4/5) || (websocket)
        var targetUri = (proxyOptions.target.host || proxyOptions.target) + req.url;
 
        logger.error('[HPM] PROXY ERROR: %s. %s -> %s', err.code, hostname, targetUri);
    }
};