implemented HTTP 301 redirect with glob matching
This commit is contained in:
parent
0047ae69f4
commit
d16f857fca
|
@ -155,7 +155,7 @@ function readConfigAndRun(args) {
|
|||
|
||||
if (ports.length === 0) {
|
||||
// I don't think we want to prevent the rest of the app from running in
|
||||
// this case like we do for TCP, do don't call reject.
|
||||
// this case like we do for TCP, so don't call reject.
|
||||
console.warn('could not bind to the desired ports for DNS');
|
||||
Object.keys(failed).forEach(function (key) {
|
||||
console.log('[error bind]', key, failed[key].code);
|
||||
|
|
|
@ -22,6 +22,12 @@ http:
|
|||
allow_insecure: false
|
||||
primary_domain: localhost.foo.daplie.me
|
||||
modules:
|
||||
- name: redirect
|
||||
domains:
|
||||
- localhost.beta.daplie.me
|
||||
status: 301
|
||||
from: /old/path/*/other/*
|
||||
to: /path/new/:2/something/:1
|
||||
- name: proxy
|
||||
domains:
|
||||
- localhost.daplie.me
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
module.exports.match = function (pattern, domainname) {
|
||||
// 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 === domainname.slice(-pattern.length);
|
||||
}
|
||||
|
||||
// pattern doesn't contains any wildcards, so exact match is required
|
||||
return pattern === domainname;
|
||||
};
|
||||
|
||||
module.exports.separatePort = function (fullHost) {
|
||||
var match = /^(.*?)(:\d+)?$/.exec(fullHost);
|
||||
|
||||
if (match[2]) {
|
||||
match[2] = match[2].replace(':', '');
|
||||
}
|
||||
|
||||
return {
|
||||
host: match[1]
|
||||
, port: match[2]
|
||||
};
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
'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;
|
||||
};
|
|
@ -4,7 +4,8 @@ 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 domainMatches = require('../domain-utils').match;
|
||||
var separatePort = require('../domain-utils').separatePort;
|
||||
var proxyRoutes = [];
|
||||
|
||||
var adminDomains = [
|
||||
|
@ -14,8 +15,16 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
, /\balpha\.localhost\./
|
||||
];
|
||||
|
||||
function moduleMatchesHost(req, mod) {
|
||||
var host = separatePort(req.headers.host).host;
|
||||
|
||||
return mod.domains.some(function (pattern) {
|
||||
return domainMatches(pattern, host);
|
||||
});
|
||||
}
|
||||
|
||||
function verifyHost(fullHost) {
|
||||
var host = /^(.*?)(:\d+)?$/.exec(fullHost)[1];
|
||||
var host = separatePort(fullHost).host;
|
||||
|
||||
if (host === 'localhost') {
|
||||
return fullHost.replace(host, 'localhost.daplie.me');
|
||||
|
@ -50,7 +59,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
return;
|
||||
}
|
||||
|
||||
var port = (/:(\d+)$/.exec(req.headers.host) || [])[1];
|
||||
var port = separatePort(req.headers.host).port;
|
||||
if (!redirecters[port]) {
|
||||
redirecters[port] = require('redirect-https')({
|
||||
port: port
|
||||
|
@ -115,24 +124,14 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
|
||||
return {
|
||||
web: function (req, res, next) {
|
||||
var hostname = req.headers.host.split(':')[0];
|
||||
var relevant = mod.domains.some(function (pattern) {
|
||||
return domainMatches(pattern, hostname);
|
||||
});
|
||||
|
||||
if (relevant) {
|
||||
if (moduleMatchesHost(req, mod)) {
|
||||
proxy.web(req, res);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
, ws: function (req, socket, head, next) {
|
||||
var hostname = req.headers.host.split(':')[0];
|
||||
var relevant = mod.domains.some(function (pattern) {
|
||||
return domainMatches(pattern, hostname);
|
||||
});
|
||||
|
||||
if (relevant) {
|
||||
if (moduleMatchesHost(req, mod)) {
|
||||
proxy.ws(req, socket, head);
|
||||
} else {
|
||||
next();
|
||||
|
@ -141,6 +140,36 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
};
|
||||
}
|
||||
|
||||
function createRedirectRoute(mod) {
|
||||
// Escape any characters that (can) have special meaning in regular expression
|
||||
// but that aren't the special characters we have interest in.
|
||||
var from = mod.from.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&');
|
||||
// Then modify the characters we are interested in so they do what we want in
|
||||
// the regular expression after being compiled.
|
||||
from = from.replace(/\*/g, '(.*)');
|
||||
var fromRe = new RegExp('^' + from + '/?$');
|
||||
|
||||
return function (req, res, next) {
|
||||
if (!moduleMatchesHost(req, mod)) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
var match = fromRe.exec(req.url);
|
||||
if (!match) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
var to = mod.to;
|
||||
match.slice(1).forEach(function (globMatch, index) {
|
||||
to = to.replace(':'+(index+1), globMatch);
|
||||
});
|
||||
res.writeHead(mod.status, { 'Location': to });
|
||||
res.end();
|
||||
};
|
||||
}
|
||||
|
||||
function createStaticRoute(mod) {
|
||||
var getStaticApp, staticApp;
|
||||
if (/:hostname/.test(mod.root)) {
|
||||
|
@ -160,13 +189,8 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
}
|
||||
|
||||
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);
|
||||
if (moduleMatchesHost(req, mod)) {
|
||||
getStaticApp(separatePort(req.headers.host).host)(req, res, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
|
@ -183,6 +207,9 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
proxyRoutes.push(proxyRoute);
|
||||
app.use(proxyRoute.web);
|
||||
}
|
||||
else if (mod.name === 'redirect') {
|
||||
app.use(createRedirectRoute(mod));
|
||||
}
|
||||
else if (mod.name === 'static') {
|
||||
app.use(createStaticRoute(mod));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ module.exports.create = function (deps, config, netHandler) {
|
|||
var parseSni = require('sni');
|
||||
var greenlock = require('greenlock');
|
||||
var localhostCerts = require('localhost.daplie.me-certificates');
|
||||
var domainMatches = require('../match-domain').match;
|
||||
var domainMatches = require('../domain-utils').match;
|
||||
|
||||
function extractSocketProp(socket, propName) {
|
||||
// remoteAddress, remotePort... ugh... https://github.com/nodejs/node/issues/8854
|
||||
|
|
Loading…
Reference in New Issue