forked from coolaj86/walnut.js
		
	
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			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;
 | |
| };
 |