'use strict';

/*
  Test the reverse proxy with curl:
  curl --proxy "" -H "X-Forwarded-Host: a-a.lod-test.istex.fr"
    -H "X-Forwarded-Server: lod-test.istex.fr" http://192.168.31.146:35267/index.html
  curl --proxy "" -H "Host: a-a.lod-test.istex.fr" http://192.168.31.146:35267/index.html
*/

var path      = require('path');
var basename  = path.basename(__filename, '.js');
var debug     = require('debug')('ezmaster:' + basename);
var instances = require('../lib/instances.js');
var cfg       = require('../lib/config.js');

var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});

module.exports = function (req, res, next) {

  if (req.headers['x-forwarded-for'] && !cfg.publicDomain) {
    return next(new Error('It\'s strange, EZmaster is behind a reverse proxy ' +
                          'so EZMASTER_PUBLIC_DOMAIN should be set'));
  }

  // totaly skip the revese proxy if EZMASTER_PUBLIC_DOMAIN is not set
  if (!cfg.publicDomain) {
    //debug('skiping reverse-proxy middleware');
    return next();
  }

  // check which instance is matching the http request
  instances.getInstances(function (err, instances) {

    if (err) { return new Error(err); }

    var host         = req.headers['host'];
    var reqHost      = req.headers['x-forwarded-host'];
    var reqSubdomain = reqHost ? reqHost.split('.') : false;

    // Two way to activate the RP:
    // with an explicit "Host" header
    // with the special X-Forwarded-Host headers
    // Makes the reverse proxy able to manage the HOST header.
    var isRpEnabled = {};
    isRpEnabled.byHost =
      cfg.publicDomain ?
      (host.slice(-cfg.publicDomain.length) === cfg.publicDomain) :
      false;
    isRpEnabled.byXForwarded =
      reqSubdomain && (reqHost.slice(-cfg.publicDomain.length) === cfg.publicDomain);

    // If Host header is used, we have to redefine reqSubdomain, reqHost and reqServer.
    if (isRpEnabled.byHost) {
      reqSubdomain = host.split('.');
      reqHost      = host;
    }

    // If isRpEnabled.
    if ((isRpEnabled.byXForwarded || isRpEnabled.byHost) && instances !== undefined) {

      var search = reqSubdomain[0].split('-');

      // Search the instance the user asked for.
      var found = Object.keys(instances)
        .map(function (z) {
          instances[z].current = instances[z].technicalName.split('-');
          instances[z].current[2] = instances[z].current[2] === undefined
            ? 0 : Number(instances[z].current[2]);
          if (Number.isNaN(Number.parseInt(instances[z].current[2]))) {
            instances[z].current[2] = 0;
          }
          return z;
        })
        .sort(function (a, b) {
          return instances[a].current[2] < instances[b].current[2];
        })
        .filter(function (x) {
          return instances[x].current[0] === search[0] && instances[x].current[1] === search[1];
        })
        .reduce(function (prev, w) {
          if (prev !== undefined) {
            return prev;
          }
          if (search[2] === undefined) {
            return w;
          }
          if (instances[w].current[0] === search[0] && instances[w].current[1] === search[1]
            && instances[w].current[2] === Number(search[2])) {
            return w;
          }
          return;
        }, undefined);

      // We feed the variable used to create the final URL.
      // This variable takes a different value if the Host header is used.
      var finalUrlLeftPart = found;
      if (isRpEnabled.byHost) {
        finalUrlLeftPart = host.split('.')[0];
      }

      // If the asked instance has been found.
      // We create the final URL and we go to it.
      if (found !== undefined) {
        var url = 'http://' + finalUrlLeftPart + ':' + instances[found].httpPort;
        proxy.web(req, res, { target: url });
        proxy.on('error', function(e) {
          console.error('reverseproxy#1.1.2', e);
          next(new Error('Bad gateway'));
        });
        return;
      }
      // Else if the asked instance has not been found.
      res.status(404).send('Instance not found');
    }
    // If not isRpEnabled.
    else {
      return next();
    }

  });
};

@@ -2225,17 +2225,30 @@
     var 
-f
+technicalNameF
 ound = O
@@ -3322,267 +3322,8 @@
 );%0A%0A
-      // We feed the variable used to create the final URL.%0A      // This variable takes a different value if the Host header is used.%0A      var finalUrlLeftPart = found;%0A      if (isRpEnabled.byHost) %7B%0A        finalUrlLeftPart = host.split('.')%5B0%5D;%0A      %7D%0A%0A
     
@@ -3425,17 +3425,30 @@
     if (
-f
+technicalNameF
 ound !==
@@ -3495,24 +3495,26 @@
 ' + 
-finalUrlLeftPart
+technicalNameFound
  + '
@@ -3528,17 +3528,30 @@
 stances%5B
-f
+technicalNameF
 ound%5D.ht

Fix reverse-proxy when host and x-forwarded-for are both present