"use strict"; module.exports = function (opts) { var escapeHtml = require("escape-html"); if (!opts) { opts = {}; } if (!isFinite(opts.port)) { opts.port = 443; } if (!opts.browsers) { opts.browsers = 301; } if (!opts.apis) { opts.apis = "meta"; } if (!Array.isArray(opts.paths)) { opts.paths = [{ match: "/" }]; } if (!("body" in opts)) { opts.body = ""; } opts.body = opts.body.replace(/{{\s+PORT\s+}}/gi, opts.port); return function (req, res, next) { if ( req.connection.encrypted || "https" === req.protocol || (opts.trustProxy && "https" === req.headers["x-forwarded-proto"]) ) { next(); return; } var url = req.originalUrl || req.url; // We don't want chrome showing the "Not Secure" badge during the redirect. var probablyBrowser = 0 === (req.headers["user-agent"] || "").indexOf("Mozilla/"); // But we don't want devs, APIs, or Bots to accidentally browse insecure. var redirect = probablyBrowser ? opts.browsers : opts.apis; var host = req.headers.host || ""; if (!/:\d+/.test(host) && 443 !== opts.port) { // we are using standard port 80, but we aren't using standard port 443 host += ":80"; } var newLocation = "https://" + host.replace(/:\d+/, ":" + opts.port) + url; //var encodedLocation = encodeURI(newLocation); var escapedLocation = escapeHtml(newLocation); var decodedLocation; try { decodedLocation = decodeURIComponent(newLocation); } catch (e) { decodedLocation = newLocation; // "#/error/?error_message=" + e.toString(); } var body = opts.body .replace(/{{\s*HTML_URL\s*}}/gi, escapeHtml(decodedLocation)) .replace(/{{\s*URL\s*}}/gi, escapedLocation) .replace(/{{\s*UNSAFE_URL\s*}}/gi, newLocation); var metaRedirect = "" + "" + '\n" + "\n" + body + "" + "\n\n"; var pathMatch; opts.paths.some(function (p) { if (!p.match) { // ignore } else if ("string" === typeof p.match) { pathMatch = url === p.match && (p.redirect || 301); } else { pathMatch = p.match.test && p.match.test(url) && (p.redirect || 301); } if (pathMatch) { redirect = pathMatch; } return pathMatch; }); // If it's not a non-0 number (because null is 0) then 'meta' is assumed. if (redirect && isFinite(redirect)) { res.statusCode = redirect; res.setHeader("Location", newLocation); } res.setHeader("Content-Type", "text/html; charset=utf-8"); res.end(metaRedirect); }; };