index.js 3.3 KB
/**
 * 后端:改写和跳转:中间件。
 *
 * 说明:
 * 该中间件使用:读该文件下的所以文件夹,以文件夹名的形式,载入该模块
 * 文件夹的名字以网站子域名的形式存在,如:guang, item
 * 每个文件夹是一个模块。
 *
 * 模块的导出形式:见 guang 模块的使用。
 * Created by TaoHuang on 2017/2/21.
 */

'use strict';

const fs = require('fs');
const _ = require('lodash');
const path = require('path');

const TYPE = require('./type');

const curDir = __dirname;
const files = fs.readdirSync(curDir);

let domainRules = {};

files.forEach((file) => {
    let info = fs.statSync(path.resolve(curDir, file));

    if (info.isDirectory() && file !== '.git') {
        domainRules[file] = require(path.resolve(curDir, file));
    }
});

/**
 * 1. origin 可接受是 正则 和 函数
 * 2. target 可接受是 匹配字符串 和 函数
 * 3. 301 是跳转 ;rewrite 改写 url
 * @returns {Function}
 */
module.exports = () => {
    return (req, res, next) => {
        let isMobile = /(nokia|iphone|android|ipad|motorola|^mot\-|softbank|foma|docomo|kddi|up\.browser|up\.link|htc|dopod|blazer|netfront|helio|hosin|huawei|novarra|CoolPad|webos|techfaith|palmsource|blackberry|alcatel|amoi|ktouch|nexian|samsung|^sam\-|s[cg]h|^lge|ericsson|philips|sagem|wellcom|bunjalloo|maui|symbian|smartphone|midp|wap|phone|windows ce|iemobile|^spice|^bird|^zte\-|longcos|pantech|gionee|^sie\-|portalmmm|jig\s browser|hiptop|^ucweb|^benq|haier|^lct|opera\s*mobi|opera\*mini|320x320|240x320|176x220)/i.test(req.get('user-agent')); // eslint-disable-line

        req.isMobile = isMobile;

        if (req.xhr) {
            return next();
        }

        let curDomainRules = domainRules[req.subdomains[0]];

        if (!curDomainRules) {
            return next();
        }

        for (let i = 0; i < curDomainRules.length; i++) {
            let rule = curDomainRules[i];

            // 匹配成功
            if (
                (_.isRegExp(rule.origin) && !_.isEmpty(rule.origin.exec(req.url))) ||
                (_.isFunction(rule.origin) && rule.origin(req))
            ) {
                let newUrl = req.url;

                if (_.isRegExp(rule.origin)) {
                    // 正则
                    if (_.isFunction(rule.target)) {
                        // 函数
                        newUrl = req.url.replace(rule.origin, _.partial(rule.target, req));
                    } else if (_.isString(rule.target)) {
                        // 字符串
                        newUrl = req.url.replace(rule.origin, req.target);
                    }
                } else if (_.isFunction(rule.origin)) {
                    // 函数
                    if (_.isFunction(rule.target)) {
                        // 函数
                        newUrl = rule.target(req);
                    } else if (_.isString(rule.target)) {
                        // 字符串
                        newUrl = rule.target;
                    }
                }

                if (rule.type === TYPE.redirect) {
                    return res.redirect(301, newUrl);
                } else if (rule.type === TYPE.rewrite) {
                    req.url = newUrl;
                    return next();
                }

                break;
            }
        }

        return next();
    };
};