redirect_index.js

/**
 * Import vendor modules
 */
const {Logger} = require('@neobeach/core');

/**
 * Simple redirect middleware
 *
 * @module @neobeach/middlewares-redirect
 * @access public
 * @since 1.0.0
 * @author Glenn de Haan
 * @copyright MIT
 *
 * @param {Object} redirects - An object containing all static and regex redirects
 * @param {Object} redirects.static - An object containing all static redirects
 * @param {Object} redirects.regex - An object containing all regex redirects
 * @param {Number} [status] - The HTTP status code used for the redirect
 * @return {function(*, *, *)}
 *
 * @example
 * const {Runtime, Server} = require('@neobeach/core');
 * const redirect = require('@neobeach/middlewares-redirect');
 *
 * const server = new Server();
 *
 * Runtime(() => {
 *    server.loadMiddlewares([redirect({static: {'/test': '/test1'}, regex: {'^/test123/.*': '/new'}})]);
 *    server.run();
 * });
 */
module.exports = (redirects = {}, status = 307) => {
    Logger.info(`[REDIRECT] Enabled! Redirect Status Code: ${status}`);

    /**
     * Define statics
     */
    const valid_status_options = [301, 302, 307, 308];

    /**
     * Check if the provided redirects are correct
     */
    if (typeof redirects === 'undefined' || typeof redirects !== 'object') {
        Logger.error("[REDIRECT] Option 'redirects' must be an Object");
        process.exit(1);
        return;
    }
    if (typeof redirects.static === 'undefined' || typeof redirects.static !== 'object') {
        Logger.error("[REDIRECT] Option 'redirects.static' must be an Object");
        process.exit(1);
        return;
    }
    if (typeof redirects.regex === 'undefined' || typeof redirects.regex !== 'object') {
        Logger.error("[REDIRECT] Option 'redirects.regex' must be an Object");
        process.exit(1);
        return;
    }

    /**
     * Check if the provided status is correct
     */
    if (valid_status_options.indexOf(status) === -1) {
        Logger.warn(`[REDIRECT] Invalid option 'status' supplied. Options: ${valid_status_options}`);
        process.exit(1);
        return;
    }

    /**
     * Return the express middleware
     */
    return (req, res, next) => {
        const reqUrl = req.originalUrl.replace(/\/$/, '');
        const nonStrippedReqUrl = req.originalUrl;

        // Check for static redirects
        if (redirects.static[reqUrl]) {
            Logger.info(`[EXPRESS][REDIRECT] Static redirect found: ${reqUrl} -> ${redirects.static[reqUrl]}`);
            res.redirect(status, redirects.static[reqUrl]);
            return;
        }

        // Check for regex redirects
        const regexKeys = Object.keys(redirects.regex);
        for (let item = 0; item < regexKeys.length; item++) {
            const reqRegex = regexKeys[item];
            const matcher = new RegExp(reqRegex);

            // Check if the provided regex matches the current url
            if (matcher.test(reqUrl) || matcher.test(nonStrippedReqUrl)) {
                const resUrl = redirects.regex[reqRegex];
                Logger.info(`[EXPRESS][REDIRECT] Regex redirect found: ${reqRegex} -> ${resUrl}`);

                // Check if the redirect url needs parts from the current url
                if (/\$[0-9]/.test(resUrl)) {
                    Logger.debug(`[EXPRESS][REDIRECT] Redirect url need parts from Current url`);

                    const match = reqUrl.match(matcher);
                    const nonStrippedMatch = nonStrippedReqUrl.match(matcher);

                    if (nonStrippedMatch !== null && nonStrippedMatch[1] !== 'undefined') {
                        Logger.debug(`[EXPRESS][REDIRECT] Redirect url parts found!`);
                        return res.redirect(status, resUrl.replace(/\$[0-9]/, `${nonStrippedMatch[1]}`));
                    }

                    // Check if we have a match available for replacement
                    if (match !== null && typeof match[1] !== 'undefined') {
                        Logger.debug(`[EXPRESS][REDIRECT] Redirect url parts found!`);
                        return res.redirect(status, resUrl.replace(/\$[0-9]/, `${match[1]}`));
                    } else {
                        Logger.debug(`[EXPRESS][REDIRECT] Redirect url parts not found!`);
                        return res.redirect(status, resUrl.replace('$1', ''));
                    }
                } else {
                    Logger.debug(`[EXPRESS][REDIRECT] Redirect url doesn't need parts from Current url`);
                    return res.redirect(status, resUrl);
                }
            }
        }

        next();
    };
};