forked from coolaj86/goldilocks.js
		
	implemented more dynamic HTTP proxying
This commit is contained in:
		
							parent
							
								
									b3b407d161
								
							
						
					
					
						commit
						ab31bae6ff
					
				@ -19,22 +19,7 @@ module.exports.create = function (deps, config) {
 | 
			
		||||
  var secureContexts = {};
 | 
			
		||||
  var tunnelAdminTlsOpts = {};
 | 
			
		||||
  var tls = require('tls');
 | 
			
		||||
 | 
			
		||||
  function domainMatches(pattern, servername) {
 | 
			
		||||
    // Everything matches '*'
 | 
			
		||||
    if (pattern === '*') {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (/^\*./.test(pattern)) {
 | 
			
		||||
      // get rid of the leading "*." to more easily check the servername against it
 | 
			
		||||
      pattern = pattern.slice(2);
 | 
			
		||||
      return pattern === servername.slice(-pattern.length);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // pattern doesn't contains any wildcards, so exact match is required
 | 
			
		||||
    return pattern === servername;
 | 
			
		||||
  }
 | 
			
		||||
  var domainMatches = require('./match-domain').match;
 | 
			
		||||
 | 
			
		||||
  var tcpRouter = {
 | 
			
		||||
    _map: { }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								lib/match-domain.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								lib/match-domain.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
module.exports.match = function (pattern, servername) {
 | 
			
		||||
  // Everything matches '*'
 | 
			
		||||
  if (pattern === '*') {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (/^\*./.test(pattern)) {
 | 
			
		||||
    // get rid of the leading "*." to more easily check the servername against it
 | 
			
		||||
    pattern = pattern.slice(2);
 | 
			
		||||
    return pattern === servername.slice(-pattern.length);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // pattern doesn't contains any wildcards, so exact match is required
 | 
			
		||||
  return pattern === servername;
 | 
			
		||||
};
 | 
			
		||||
@ -1,34 +1,66 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (deps, conf) {
 | 
			
		||||
  // This should be able to handle things like default web path (i.e. /srv/www/hostname),
 | 
			
		||||
  // no-www redirect, and transpilation of static assets (i.e. cached versions of raw html)
 | 
			
		||||
  // but right now it's a very dumb proxy
 | 
			
		||||
  var app = require('express')();
 | 
			
		||||
  var domainMatches = require('../match-domain').match;
 | 
			
		||||
 | 
			
		||||
  function createConnection(conn) {
 | 
			
		||||
    var opts = conn.__opts;
 | 
			
		||||
    var newConn = deps.net.createConnection({
 | 
			
		||||
      port: conf.http.proxy.port
 | 
			
		||||
    , host: '127.0.0.1'
 | 
			
		||||
 | 
			
		||||
    , servername: opts.servername
 | 
			
		||||
    , data: opts.data
 | 
			
		||||
    , remoteFamily: opts.family || conn.remoteFamily
 | 
			
		||||
    , remoteAddress: opts.address || conn.remoteAddress
 | 
			
		||||
    , remotePort: opts.port || conn.remotePort
 | 
			
		||||
    }, function () {
 | 
			
		||||
      //console.log("[=>] first packet from tunneler to '" + cid + "' as '" + opts.service + "'", opts.data.byteLength);
 | 
			
		||||
      // this will happen before 'data' is triggered
 | 
			
		||||
      //newConn.write(opts.data);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    newConn.pipe(conn);
 | 
			
		||||
    conn.pipe(newConn);
 | 
			
		||||
  // 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.
 | 
			
		||||
  var redirecters = {};
 | 
			
		||||
  function redirectHttps(req, res, next) {
 | 
			
		||||
    var port = req.headers.host.split(':')[1];
 | 
			
		||||
    var redirecter = redirecters[port];
 | 
			
		||||
    if (!redirecter) {
 | 
			
		||||
      redirecter = redirecters[port] = require('redirect-https')({port: port});
 | 
			
		||||
    }
 | 
			
		||||
    redirecter(req, res, next);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    emit: function (type, conn) {
 | 
			
		||||
      createConnection(conn);
 | 
			
		||||
  function respond404(req, res) {
 | 
			
		||||
    res.writeHead(404);
 | 
			
		||||
    res.end('Not Found');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function createProxyRoute(mod) {
 | 
			
		||||
    // This is the easiest way to override the createConnections function the proxy
 | 
			
		||||
    // module uses, but take note the since we don't have control over where this is
 | 
			
		||||
    // called the extra options availabled will be different.
 | 
			
		||||
    var agent = new require('http').Agent({});
 | 
			
		||||
    agent.createConnection = deps.net.createConnection;
 | 
			
		||||
 | 
			
		||||
    var proxy = require('http-proxy').createProxyServer({
 | 
			
		||||
      agent: agent
 | 
			
		||||
    , target: 'http://' + mod.address
 | 
			
		||||
    , xfwd: true
 | 
			
		||||
    , toProxy: true
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return function (req, res, next) {
 | 
			
		||||
      var hostname = req.headers.host.split(':')[0];
 | 
			
		||||
      var relevant = mod.domains.some(function (pattern) {
 | 
			
		||||
        return domainMatches(pattern, hostname);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (relevant) {
 | 
			
		||||
        proxy.web(req, res);
 | 
			
		||||
      } else {
 | 
			
		||||
        next();
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  app.use(redirectHttps);
 | 
			
		||||
 | 
			
		||||
  (conf.http.modules || []).forEach(function (mod) {
 | 
			
		||||
    if (mod.name === 'proxy') {
 | 
			
		||||
      app.use(createProxyRoute(mod));
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
    else {
 | 
			
		||||
      console.warn('unknown HTTP module', mod);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  app.use(respond404);
 | 
			
		||||
  return require('http').createServer(app);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,7 @@
 | 
			
		||||
    "finalhandler": "^0.4.0",
 | 
			
		||||
    "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
 | 
			
		||||
    "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master",
 | 
			
		||||
    "http-proxy": "^1.16.2",
 | 
			
		||||
    "httpolyglot": "^0.1.1",
 | 
			
		||||
    "ipaddr.js": "git+https://github.com/whitequark/ipaddr.js.git#v1.3.0",
 | 
			
		||||
    "ipify": "^1.1.0",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user