|
|
- 'use strict';
-
- var url = require('url');
-
- exports = module.exports = function historyApiFallback(options) {
- options = options || {};
- var logger = getLogger(options);
-
- return function(req, res, next) {
- var headers = req.headers;
- if (req.method !== 'GET') {
- logger(
- 'Not rewriting',
- req.method,
- req.url,
- 'because the method is not GET.'
- );
- return next();
- } else if (!headers || typeof headers.accept !== 'string') {
- logger(
- 'Not rewriting',
- req.method,
- req.url,
- 'because the client did not send an HTTP accept header.'
- );
- return next();
- } else if (headers.accept.indexOf('application/json') === 0) {
- logger(
- 'Not rewriting',
- req.method,
- req.url,
- 'because the client prefers JSON.'
- );
- return next();
- } else if (!acceptsHtml(headers.accept, options)) {
- logger(
- 'Not rewriting',
- req.method,
- req.url,
- 'because the client does not accept HTML.'
- );
- return next();
- }
-
- var parsedUrl = url.parse(req.url);
- var rewriteTarget;
- options.rewrites = options.rewrites || [];
- for (var i = 0; i < options.rewrites.length; i++) {
- var rewrite = options.rewrites[i];
- var match = parsedUrl.pathname.match(rewrite.from);
- if (match !== null) {
- rewriteTarget = evaluateRewriteRule(parsedUrl, match, rewrite.to, req);
-
- if(rewriteTarget.charAt(0) !== '/') {
- logger(
- 'We recommend using an absolute path for the rewrite target.',
- 'Received a non-absolute rewrite target',
- rewriteTarget,
- 'for URL',
- req.url
- );
- }
-
- logger('Rewriting', req.method, req.url, 'to', rewriteTarget);
- req.url = rewriteTarget;
- return next();
- }
- }
-
- var pathname = parsedUrl.pathname;
- if (pathname.lastIndexOf('.') > pathname.lastIndexOf('/') &&
- options.disableDotRule !== true) {
- logger(
- 'Not rewriting',
- req.method,
- req.url,
- 'because the path includes a dot (.) character.'
- );
- return next();
- }
-
- rewriteTarget = options.index || '/index.html';
- logger('Rewriting', req.method, req.url, 'to', rewriteTarget);
- req.url = rewriteTarget;
- next();
- };
- };
-
- function evaluateRewriteRule(parsedUrl, match, rule, req) {
- if (typeof rule === 'string') {
- return rule;
- } else if (typeof rule !== 'function') {
- throw new Error('Rewrite rule can only be of type string or function.');
- }
-
- return rule({
- parsedUrl: parsedUrl,
- match: match,
- request: req
- });
- }
-
- function acceptsHtml(header, options) {
- options.htmlAcceptHeaders = options.htmlAcceptHeaders || ['text/html', '*/*'];
- for (var i = 0; i < options.htmlAcceptHeaders.length; i++) {
- if (header.indexOf(options.htmlAcceptHeaders[i]) !== -1) {
- return true;
- }
- }
- return false;
- }
-
- function getLogger(options) {
- if (options && options.logger) {
- return options.logger;
- } else if (options && options.verbose) {
- return console.log.bind(console);
- }
- return function(){};
- }
|