geoip_index.js

/**
 * Import modules
 */
const {Logger} = require('@neobeach/core');
const expressGeoIp = require('express-geoip');

/**
 * Checks if we should redirect based on GEO-IP
 *
 * @module @neobeach/middlewares-geoip
 * @access public
 * @since 1.0.0
 * @author Glenn de Haan
 * @copyright MIT
 *
 * @param {Object} routing - Object with blueprint of projects routing.
 * @param {String} defaultCountryCode - When req.ip is not found or recognized use this country code.
 * @param {Number} [statusCode] - The status code to use on the redirect.
 * @param {Boolean} [debug] - Boolean to have extra logging for debugging.
 * @return {function(*, *, *)}
 *
 * @example
 * const {Runtime, Server} = require('@neobeach/core');
 * const geoip = require('@neobeach/middlewares-geoip');
 *
 * const server = new Server();
 *
 * Runtime(() => {
 *      server.loadMiddlewares([geoip({'nl': 'nl-NL'}, 'nl', 301, false)]);
 *      server.run();
 * });
 */
module.exports = (routing, defaultCountryCode, statusCode = 307, debug = false) => {
    Logger.info(`[GEOIP] Enabled! Routing: ${JSON.stringify(routing)}, Default Country Code: ${defaultCountryCode}, Redirect Status Code: ${statusCode}`);

    return (req, res, next) => {
        /**
         * Check if routing is correct
         */
        if(typeof routing === "undefined" || typeof routing !== "object") {
            Logger.error("[GEOIP] Routing object is not correct");
            process.exit(1);
            return;
        }

        /**
         * Check if defaultCountryCode is correct
         */
        if (typeof defaultCountryCode === "undefined" || typeof defaultCountryCode !== "string" || defaultCountryCode === "") {
            Logger.error("[GEOIP] defaultCountryCode is not correct");
            process.exit(1);
            return;
        }

        // Check if ip is in request and check if ip address is know otherwise use default country code
        const countryCode = req.ip ? expressGeoIp('unknown').getCountryCode(req.ip) === "unknown" ? defaultCountryCode : expressGeoIp('unknown').getCountryCode(req.ip) : defaultCountryCode;

        const urlWithoutParams = req.originalUrl.split("?")[0];

        if (urlWithoutParams === "/") {
            if (routing[countryCode.toLowerCase()]) {
                if (debug) {
                    Logger.info(`[REDIRECT] Based on GeoIP: ${countryCode} -> ${routing[countryCode.toLowerCase()]}`);
                }
                res.redirect(statusCode, routing[countryCode.toLowerCase()]);
                return;
            } else {
                res.redirect(statusCode, defaultCountryCode);
                return;
            }
        }

        next();
    }
};