walnut.js/lib/hostname-redirects.js

123 lines
3.1 KiB
JavaScript

'use strict';
// TODO detect infinite redirects
module.exports.compile = module.exports.sortOpts = function (redirects) {
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;
};