2015-11-21 06:42:23 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// TODO detect infinite redirects
|
|
|
|
|
2015-11-21 12:36:22 +00:00
|
|
|
module.exports.compile = module.exports.sortOpts = function (redirects) {
|
2015-11-21 06:42:23 +00:00
|
|
|
var dups = {};
|
|
|
|
var results = {
|
|
|
|
conflicts: {}
|
|
|
|
, patterns: []
|
|
|
|
, matchesMap: {}
|
|
|
|
};
|
|
|
|
|
|
|
|
redirects.forEach(function (r) {
|
|
|
|
var bare;
|
|
|
|
var www;
|
|
|
|
|
|
|
|
if ('.' === r.id[0]) {
|
|
|
|
// for consistency
|
|
|
|
// TODO this should happen at the database level
|
|
|
|
r.id = '*' + r.id;
|
|
|
|
}
|
|
|
|
if ('*' === r.id[0]) {
|
|
|
|
// TODO check that we are not trying to redirect a tld (.com, .co.uk, .org, etc)
|
|
|
|
// tlds should follow the global policy
|
|
|
|
if (r.id[1] && '.' !== r.id[1]) {
|
|
|
|
// this is not a good place to throw as the consequences of a bug would be
|
|
|
|
// very bad, but errors should never be silent, so we'll compromise
|
|
|
|
console.warn("[NON-FATAL ERROR]: ignoring redirect pattern '" + r.id + "'");
|
|
|
|
results.conflicts[r.id] = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nix the '*' for easier matching
|
|
|
|
r.id = r.id.slice(1);
|
|
|
|
if (!r.id) {
|
|
|
|
r.id = '*';
|
|
|
|
}
|
|
|
|
if (dups[r.id]) {
|
|
|
|
results.conflicts[r.id] = r;
|
|
|
|
console.warn("[NON-FATAL ERROR]: duplicate entry for redirect pattern '" + r.id + "'");
|
|
|
|
}
|
|
|
|
dups[r.id] = true;
|
|
|
|
results.patterns.push(r);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bare = r.id.replace(/^www\./i, '');
|
|
|
|
www = r.id.replace(/^(www\.)?/i, 'www.');
|
|
|
|
|
|
|
|
if (true === r.value) {
|
|
|
|
// implicit add www
|
|
|
|
results.matchesMap[bare] = www;
|
|
|
|
results.matchesMap[www] = www;
|
|
|
|
} else if (false === r.value) {
|
|
|
|
// implicit remove www
|
|
|
|
results.matchesMap[bare] = bare;
|
|
|
|
results.matchesMap[www] = bare;
|
|
|
|
} else if (!r.value) {
|
|
|
|
// (null, '', 0, undefined)
|
|
|
|
// explicitly no change
|
|
|
|
results.matchesMap[r.id] = r.id;
|
|
|
|
} else {
|
|
|
|
// explicit value
|
|
|
|
results.matchesMap[r.id] = r.value;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
results.patterns.sort(function (a, b) {
|
|
|
|
return b.id.length - a.id.length;
|
|
|
|
});
|
|
|
|
|
|
|
|
return results;
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports.redirectTo = function (hostname, opts) {
|
|
|
|
var redir = opts.matchesMap[hostname];
|
|
|
|
|
|
|
|
if (redir) {
|
|
|
|
if (redir === hostname) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return redir;
|
|
|
|
}
|
|
|
|
|
|
|
|
// longest to shortest
|
|
|
|
var hasWww = ('www.' === hostname.slice(0, 4));
|
|
|
|
//var noWww = (hasWww && hostname.slice(4)) || hostname;
|
|
|
|
//var yesWww = (hasWww && hostname) || ('www.' + hostname);
|
|
|
|
|
|
|
|
redir = false;
|
|
|
|
opts.patterns.some(function (r) {
|
|
|
|
// r.id begins with a dot, such as '.foo.example.com'
|
|
|
|
if (r.id !== hostname.slice(hostname.length - r.id.length)) {
|
|
|
|
// except for the default, which is an *
|
|
|
|
if ('*' !== r.id) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (true === r.value) {
|
|
|
|
// implicit add www
|
|
|
|
redir = hasWww ? hostname : ('www.' + hostname);
|
|
|
|
} else if (false === r.value) {
|
|
|
|
// implicit remove www
|
|
|
|
redir = hasWww ? hostname.slice(4) : hostname;
|
|
|
|
} else if (!r.value) {
|
|
|
|
// (null, '', 0, undefined)
|
|
|
|
// explicitly no change
|
|
|
|
redir = false;
|
|
|
|
} else {
|
|
|
|
// explicit value
|
|
|
|
redir = r.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (redir === hostname) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return redir;
|
|
|
|
};
|