| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 | '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(){};}
 |