forked from coolaj86/goldilocks.js
		
	added ability to scope config by domain (issue #25)
This commit is contained in:
		
							parent
							
								
									1f8e44947f
								
							
						
					
					
						commit
						1e3021c669
					
				@ -10,6 +10,12 @@ tcp:
 | 
			
		||||
      address: '127.0.0.1:8022'
 | 
			
		||||
 | 
			
		||||
tls:
 | 
			
		||||
  domains:
 | 
			
		||||
    - names:
 | 
			
		||||
        - localhost.gamma.daplie.me
 | 
			
		||||
      modules:
 | 
			
		||||
        - name: proxy
 | 
			
		||||
          address: '127.0.0.1:6443'
 | 
			
		||||
  modules:
 | 
			
		||||
    - name: proxy
 | 
			
		||||
      domains:
 | 
			
		||||
@ -21,6 +27,16 @@ http:
 | 
			
		||||
  trust_proxy: true
 | 
			
		||||
  allow_insecure: false
 | 
			
		||||
  primary_domain: localhost.foo.daplie.me
 | 
			
		||||
  domains:
 | 
			
		||||
    - names:
 | 
			
		||||
        - localhost.baz.daplie.me
 | 
			
		||||
      modules:
 | 
			
		||||
        - name: redirect
 | 
			
		||||
          from: /nowhere/in/particular
 | 
			
		||||
          to: /just/an/example
 | 
			
		||||
        - name: proxy
 | 
			
		||||
          address: '127.0.0.1:3001'
 | 
			
		||||
 | 
			
		||||
  modules:
 | 
			
		||||
    - name: redirect
 | 
			
		||||
      domains:
 | 
			
		||||
 | 
			
		||||
@ -70,14 +70,43 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function moduleMatchesHost(req, mod) {
 | 
			
		||||
  function hostMatchesDomains(req, domains) {
 | 
			
		||||
    var host = separatePort((req.headers || req).host).host;
 | 
			
		||||
 | 
			
		||||
    return mod.domains.some(function (pattern) {
 | 
			
		||||
    return domains.some(function (pattern) {
 | 
			
		||||
      return domainMatches(pattern, host);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function determinePrimaryHost() {
 | 
			
		||||
    var result;
 | 
			
		||||
    if (Array.isArray(conf.http.domains)) {
 | 
			
		||||
      conf.http.domains.some(function (dom) {
 | 
			
		||||
        return dom.names.some(function (domain) {
 | 
			
		||||
          if (domain[0] !== '*') {
 | 
			
		||||
            result = domain;
 | 
			
		||||
            return true;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    if (result) {
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Array.isArray(conf.http.modules)) {
 | 
			
		||||
      conf.http.modules.some(function (mod) {
 | 
			
		||||
        return mod.domains.some(function (domain) {
 | 
			
		||||
          if (domain[0] !== '*') {
 | 
			
		||||
            result = domain;
 | 
			
		||||
            return true;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // We handle both HTTPS and HTTP traffic on the same ports, and we want to redirect
 | 
			
		||||
  // any unencrypted requests to the same port they came from unless it came in on
 | 
			
		||||
  // the default HTTP port, in which case there wont be a port specified in the host.
 | 
			
		||||
@ -100,18 +129,14 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
    // Test for IPv4 and IPv6 addresses. These patterns will match some invalid addresses,
 | 
			
		||||
    // but since those still won't be valid domains that won't really be a problem.
 | 
			
		||||
    if (ipv4Re.test(host.host) || ipv6Re.test(host.host)) {
 | 
			
		||||
      if (!conf.http.primaryDomain) {
 | 
			
		||||
        (conf.http.modules || []).some(function (mod) {
 | 
			
		||||
          return mod.domains.some(function (domain) {
 | 
			
		||||
            if (domain[0] !== '*') {
 | 
			
		||||
              conf.http.primaryDomain = domain;
 | 
			
		||||
              return true;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      var dest;
 | 
			
		||||
      if (conf.http.primaryDomain) {
 | 
			
		||||
        req.headers.host = conf.http.primaryDomain + (host.port ? ':'+host.port : '');
 | 
			
		||||
        dest = conf.http.primaryDomain;
 | 
			
		||||
      } else {
 | 
			
		||||
        dest = determinePrimaryHost();
 | 
			
		||||
      }
 | 
			
		||||
      if (dest) {
 | 
			
		||||
        req.headers.host = dest + (host.port ? ':'+host.port : '');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -175,10 +200,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function checkProxy(mod, conn, opts, headers) {
 | 
			
		||||
    if (!moduleMatchesHost(headers, mod)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var index = opts.firstChunk.indexOf('\r\n\r\n');
 | 
			
		||||
    var body = opts.firstChunk.slice(index);
 | 
			
		||||
 | 
			
		||||
@ -216,10 +237,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function checkRedirect(mod, conn, opts, headers) {
 | 
			
		||||
    if (!moduleMatchesHost(headers, mod)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!mod.fromRe || mod.fromRe.origSrc !== mod.from) {
 | 
			
		||||
      // Escape any characters that (can) have special meaning in regular expression
 | 
			
		||||
      // but that aren't the special characters we have interest in.
 | 
			
		||||
@ -283,10 +300,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  function checkStatic(mod, conn, opts, headers) {
 | 
			
		||||
    if (!moduleMatchesHost(headers, mod)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var rootDir = mod.root.replace(':hostname', separatePort(headers.host).host);
 | 
			
		||||
    return statAsync(rootDir)
 | 
			
		||||
      .then(function (stats) {
 | 
			
		||||
@ -309,6 +322,12 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
      ;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var moduleChecks = {
 | 
			
		||||
    proxy:    checkProxy
 | 
			
		||||
  , redirect: checkRedirect
 | 
			
		||||
  , static:   checkStatic
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  function handleConnection(conn) {
 | 
			
		||||
    var opts = conn.__opts;
 | 
			
		||||
    parseHeaders(conn, opts)
 | 
			
		||||
@ -318,19 +337,34 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
 | 
			
		||||
        if (checkAdmin(conn, opts, headers)) { return; }
 | 
			
		||||
 | 
			
		||||
        var prom = PromiseA.resolve(false);
 | 
			
		||||
        (conf.http.domains || []).forEach(function (dom) {
 | 
			
		||||
          prom = prom.then(function (handled) {
 | 
			
		||||
            if (handled) {
 | 
			
		||||
              return handled;
 | 
			
		||||
            }
 | 
			
		||||
            if (!hostMatchesDomains(headers, dom.names)) {
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return dom.modules.some(function (mod) {
 | 
			
		||||
              if (moduleChecks[mod.name]) {
 | 
			
		||||
                return moduleChecks[mod.name](mod, conn, opts, headers);
 | 
			
		||||
              }
 | 
			
		||||
              console.warn('unknown HTTP module under domains', dom.names.join(','), mod);
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
        (conf.http.modules || []).forEach(function (mod) {
 | 
			
		||||
          prom = prom.then(function (handled) {
 | 
			
		||||
            if (handled) {
 | 
			
		||||
              return handled;
 | 
			
		||||
            }
 | 
			
		||||
            if (mod.name === 'proxy') {
 | 
			
		||||
              return checkProxy(mod, conn, opts, headers);
 | 
			
		||||
            if (!hostMatchesDomains(headers, mod.domains)) {
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
            if (mod.name === 'redirect') {
 | 
			
		||||
              return checkRedirect(mod, conn, opts, headers);
 | 
			
		||||
            }
 | 
			
		||||
            if (mod.name === 'static') {
 | 
			
		||||
              return checkStatic(mod, conn, opts, headers);
 | 
			
		||||
 | 
			
		||||
            if (moduleChecks[mod.name]) {
 | 
			
		||||
              return moduleChecks[mod.name](mod, conn, opts, headers);
 | 
			
		||||
            }
 | 
			
		||||
            console.warn('unknown HTTP module found', mod);
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
@ -204,6 +204,7 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
        return new tls.TLSSocket(wrapSocket(socket, opts), tlsOpts);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function terminate(socket, opts) {
 | 
			
		||||
@ -244,30 +245,45 @@ module.exports.create = function (deps, config, netHandler) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var handled = (config.tls.modules || []).some(function (mod) {
 | 
			
		||||
      var relevant = mod.domains.some(function (pattern) {
 | 
			
		||||
    function checkModule(mod) {
 | 
			
		||||
      if (mod.name === 'proxy') {
 | 
			
		||||
        return proxy(socket, opts, mod);
 | 
			
		||||
      }
 | 
			
		||||
      if (mod.name !== 'acme') {
 | 
			
		||||
        console.error('saw unknown TLS module', mod);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var handled = (config.tls.domains || []).some(function (dom) {
 | 
			
		||||
      var relevant = dom.names.some(function (pattern) {
 | 
			
		||||
        return domainMatches(pattern, opts.servername);
 | 
			
		||||
      });
 | 
			
		||||
      if (!relevant) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (mod.name === 'proxy') {
 | 
			
		||||
        proxy(socket, opts, mod);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        console.error('saw unknown TLS module', mod);
 | 
			
		||||
      return dom.modules.some(checkModule);
 | 
			
		||||
    });
 | 
			
		||||
    if (handled) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handled = (config.tls.modules || []).some(function (mod) {
 | 
			
		||||
      var relevant = mod.domains.some(function (pattern) {
 | 
			
		||||
        return domainMatches(pattern, opts.servername);
 | 
			
		||||
      });
 | 
			
		||||
      if (!relevant) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return true;
 | 
			
		||||
      return checkModule(mod);
 | 
			
		||||
    });
 | 
			
		||||
    if (handled) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: figure out all of the domains that the other modules intend to handle, and only
 | 
			
		||||
    // terminate those ones, closing connections for all others.
 | 
			
		||||
    if (!handled) {
 | 
			
		||||
      terminate(socket, opts);
 | 
			
		||||
    }
 | 
			
		||||
    terminate(socket, opts);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user