Skip to content

Commit

Permalink
processRedirect
Browse files Browse the repository at this point in the history
  • Loading branch information
orthagonal committed Sep 25, 2018
1 parent d7a8f3c commit 355d195
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 72 deletions.
107 changes: 35 additions & 72 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
'use strict';
const useragent = require('useragent');
const paramReplacer = require('./paramReplacer');
const Call = require('call');
const querystring = require('query-string');
const { parse } = require('url');

const defaults = {
statusCode: 301,
Expand All @@ -24,42 +20,7 @@ module.exports = (server, pluginOptions) => {
server.event('redirect');

// turn a redirect into a redirection URL and a status code:
const processRedirect = async(request, routeSpec, match = false) => {
// get all the info for doing the redirect from the route spec:
const statusCode = routeSpec.statusCode || options.statusCode;
const routePath = typeof routeSpec === 'string' ? routeSpec : routeSpec.destination;
const route = request.route.path;
const redirectTo = paramReplacer(routePath, match ? match.params : request.params);
const redirectToUrl = parse(redirectTo, true);
// lump all queries together:
const allQueries = Object.assign({}, request.query, redirectToUrl.query);
// if needed, add the queries to the parsed url:
if (Object.keys(allQueries).length > 0) {
redirectToUrl.search = `?${querystring.stringify(allQueries)}`;
}
// let the url parser format the correct redirect Location:
const fullRedirectLocation = redirectToUrl.format();

let from = request.path;
if (Object.keys(request.query).length !== 0) {
from = `${from}?${querystring.stringify(request.query)}`;
}
// log the route info:
server.log(['hapi-redirect', 'redirect', 'info'], {
remoteAddress: `${request.info.remoteAddress}:${request.info.remotePort}`,
host: request.info.host,
userAgent: request.headers['user-agent'],
browser: useragent.parse(request.headers['user-agent']).toString(),
referrer: request.info.referrer,
routePath: route,
to: fullRedirectLocation,
from
});

// now emit the event and do the redirect:
await server.events.emit('redirect', (request, fullRedirectLocation));
return { statusCode, fullRedirectLocation };
};
const processRedirect = require('./processRedirect');

// let them add additional routes:
server.expose('register', (additionalRoutes) => {
Expand All @@ -70,7 +31,7 @@ module.exports = (server, pluginOptions) => {
method: '*',
path,
async handler(request, h) {
const { statusCode, fullRedirectLocation } = await processRedirect(request, additionalRoutes[path]);
const { statusCode, fullRedirectLocation } = await processRedirect(request, additionalRoutes[path], server, options);
return h.redirect(fullRedirectLocation).code(statusCode);
}
});
Expand All @@ -81,38 +42,40 @@ module.exports = (server, pluginOptions) => {
server.plugins['hapi-redirects'].register(options.redirects);
}

server.ext('onPreResponse', async (request, h) => {
// does not interfere if it's not a 404 error
if ((request.response.statusCode && request.response.statusCode !== 404) || (request.response.isBoom && request.response.output.statusCode !== 404)) {
return h.continue;
}
// if it's 404 then look up a redirect, first get dynamic redirects:
const dynamicRedirects = options.dynamicRedirects ? options.dynamicRedirects : (redirectOptions) => [];
if (options.dynamicRedirects) {
server.ext('onPreResponse', async (request, h) => {
// does not interfere if it's not a 404 error
if ((request.response.statusCode && request.response.statusCode !== 404) || (request.response.isBoom && request.response.output.statusCode !== 404)) {
return h.continue;
}
// if it's 404 then look up a redirect, first get dynamic redirects:
const dynamicRedirects = options.dynamicRedirects ? options.dynamicRedirects : (redirectOptions) => [];

// the plugin options will be passed to your custom 'dynamicRedirects' function:
let dynamicRouteTable;
try {
dynamicRouteTable = await dynamicRedirects(options);
} catch (err) {
server.log(['hapi-redirect', 'error'], err);
return h.continue;
}
const router = new Call.Router();
const path = request.path;
// the plugin options will be passed to your custom 'dynamicRedirects' function:
let dynamicRouteTable;
try {
dynamicRouteTable = await dynamicRedirects(options);
} catch (err) {
server.log(['hapi-redirect', 'error'], err);
return h.continue;
}
const router = new Call.Router();
const path = request.path;

// load the routes:
Object.keys(dynamicRouteTable).forEach((source) => {
router.add({ method: 'get', path: source });
// load the routes:
Object.keys(dynamicRouteTable).forEach((source) => {
router.add({ method: 'get', path: source });
});
// try to match the incoming route:
const host = request.headers.host;
const match = router.route('get', path, host);
if (!match.route) {
return h.continue;
}
// get the spec data for the matching route from either vhost or the route table:
const routeSpec = dynamicRouteTable[match.route];
const { statusCode, fullRedirectLocation } = await processRedirect(request, routeSpec, server, options, match);
return h.redirect(fullRedirectLocation).code(statusCode).takeover();
});
// try to match the incoming route:
const host = request.headers.host;
const match = router.route('get', path, host);
if (!match.route) {
return h.continue;
}
// get the spec data for the matching route from either vhost or the route table:
const routeSpec = dynamicRouteTable[match.route];
const { statusCode, fullRedirectLocation } = await processRedirect(request, routeSpec, match);
return h.redirect(fullRedirectLocation).code(statusCode).takeover();
});
}
};
41 changes: 41 additions & 0 deletions lib/processRedirect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const paramReplacer = require('./paramReplacer');
const querystring = require('query-string');
const { parse } = require('url');
const useragent = require('useragent');

module.exports = async(request, routeSpec, server, options, match = false) => {
// get all the info for doing the redirect from the route spec:
const statusCode = routeSpec.statusCode || options.statusCode;
const routePath = typeof routeSpec === 'string' ? routeSpec : routeSpec.destination;
const route = request.route.path;
const redirectTo = paramReplacer(routePath, match ? match.params : request.params);
const redirectToUrl = parse(redirectTo, true);
// lump all queries together:
const allQueries = Object.assign({}, request.query, redirectToUrl.query);
// if needed, add the queries to the parsed url:
if (Object.keys(allQueries).length > 0) {
redirectToUrl.search = `?${querystring.stringify(allQueries)}`;
}
// let the url parser format the correct redirect Location:
const fullRedirectLocation = redirectToUrl.format();

let from = request.path;
if (Object.keys(request.query).length !== 0) {
from = `${from}?${querystring.stringify(request.query)}`;
}
// log the route info:
server.log(['hapi-redirect', 'redirect', 'info'], {
remoteAddress: `${request.info.remoteAddress}:${request.info.remotePort}`,
host: request.info.host,
userAgent: request.headers['user-agent'],
browser: useragent.parse(request.headers['user-agent']).toString(),
referrer: request.info.referrer,
routePath: route,
to: fullRedirectLocation,
from
});

// now emit the event and do the redirect:
await server.events.emit('redirect', (request, fullRedirectLocation));
return { statusCode, fullRedirectLocation };
};

0 comments on commit 355d195

Please sign in to comment.