147 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| module.exports.create = function (deps, conf, greenlockMiddleware) {
 | |
|   var express = require('express');
 | |
|   var app = express();
 | |
|   var adminApp = require('./admin').create(deps, conf);
 | |
|   var domainMatches = require('../match-domain').match;
 | |
| 
 | |
|   var adminDomains = [
 | |
|     /\blocalhost\.admin\./
 | |
|   , /\blocalhost\.alpha\./
 | |
|   , /\badmin\.localhost\./
 | |
|   , /\balpha\.localhost\./
 | |
|   ];
 | |
| 
 | |
|   // 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];
 | |
|     if (!redirecters[port]) {
 | |
|       redirecters[port] = require('redirect-https')({
 | |
|         port: port
 | |
|       , trustProxy: conf.http.trustProxy
 | |
|       });
 | |
|     }
 | |
|     redirecters[port](req, res, next);
 | |
|   }
 | |
| 
 | |
|   function handleAdmin(req, res, next) {
 | |
|     var admin = adminDomains.some(function (re) {
 | |
|       return re.test(req.headers.host);
 | |
|     });
 | |
| 
 | |
|     if (admin) {
 | |
|       adminApp(req, res);
 | |
|     } else {
 | |
|       next();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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
 | |
|     });
 | |
| 
 | |
|     // We want to override the default value for some headers with the extra information we
 | |
|     // have available to us in the opts object attached to the connection.
 | |
|     proxy.on('proxyReq', function (proxyReq, req) {
 | |
|       var conn = req.connection;
 | |
|       var opts = conn.__opts;
 | |
|       proxyReq.setHeader('X-Forwarded-For', opts.remoteAddress || conn.remoteAddress);
 | |
|     });
 | |
| 
 | |
|     proxy.on('error', function (err, req, res) {
 | |
|       console.log(err);
 | |
|       res.writeHead(502);
 | |
|       if (err.code === 'ECONNREFUSED') {
 | |
|         res.end('The connection was refused. Most likely the service being connected to '
 | |
|           + 'has stopped running or the configuration is wrong.');
 | |
|       }
 | |
|       else {
 | |
|         res.end('Bad Gateway: ' + err.code);
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     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();
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   function createStaticRoute(mod) {
 | |
|     var getStaticApp, staticApp;
 | |
|     if (/:hostname/.test(mod.root)) {
 | |
|       staticApp = {};
 | |
|       getStaticApp = function (hostname) {
 | |
|         if (!staticApp[hostname]) {
 | |
|           staticApp[hostname] = express.static(mod.root.replace(':hostname', hostname));
 | |
|         }
 | |
|         return staticApp[hostname];
 | |
|       };
 | |
|     }
 | |
|     else {
 | |
|       staticApp = express.static(mod.root);
 | |
|       getStaticApp = function () {
 | |
|         return staticApp;
 | |
|       };
 | |
|     }
 | |
| 
 | |
|     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) {
 | |
|         getStaticApp(hostname)(req, res, next);
 | |
|       } else {
 | |
|         next();
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   app.use(greenlockMiddleware);
 | |
|   app.use(redirectHttps);
 | |
|   app.use(handleAdmin);
 | |
| 
 | |
|   (conf.http.modules || []).forEach(function (mod) {
 | |
|     if (mod.name === 'proxy') {
 | |
|       app.use(createProxyRoute(mod));
 | |
|     }
 | |
|     else if (mod.name === 'static') {
 | |
|       app.use(createStaticRoute(mod));
 | |
|     }
 | |
|     else {
 | |
|       console.warn('unknown HTTP module', mod);
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   app.use(respond404);
 | |
|   return require('http').createServer(app);
 | |
| };
 |