index.js
4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* 后端:改写和跳转:中间件。
*
* 说明:
* 该中间件使用:使用文件夹下 rule 的所有的文件,以文件名的形式,载入该模块
* 文件的名字建议以网站子域名的形式存在,如:guang, item
* 每个文件夹是一个模块。
*
* 模块的导出形式:见 guang 模块的使用。
* Created by TaoHuang on 2017/2/21.
*/
'use strict';
const fs = require('fs');
const _ = require('lodash');
const path = require('path');
const helpers = global.yoho.helpers;
const logger = global.yoho.logger;
const TYPE = require('./type');
const DIR = './rules/';
const curDir = path.resolve(__dirname, DIR);
const files = fs.readdirSync(curDir);
let domainRules = {};
// 载入模块
files.forEach((file) => {
let info = fs.statSync(path.resolve(curDir, file));
if (info.isFile()) {
let module = path.basename(file, '.js');
let loadPath = DIR + module;
try {
domainRules[module] = require(loadPath);
} catch (e) {
logger.error('load rules wrong', e);
}
}
});
const loadRule = (domain) => {
return domainRules[domain] || domain.default;
};
/**
* 1. origin 可接受是 正则 , 函数, 纯字符串
* 2. target 可接受是 匹配字符串 , 函数, 纯字符串
* 3. 301: 跳转
* rewrite: 改写 url
* @returns {Function}
*/
module.exports = () => {
return (req, res, next) => {
if (req.subdomains.length > 1 && req.subdomains[1] === 'www') {
return res.redirect(301, helpers.urlFormat(req.path, req.query || '', req.subdomains[0]));
}
req.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
if (req.xhr) {
return next();
}
/***************************************************************/
let rules = loadRule(req.subdomains[0]);
if (!rules) {
return next();
}
for (let i = 0; i < rules.length; i++) {
let rule = rules[i];
// 匹配成功
if (
(_.isRegExp(rule.origin) && !_.isEmpty(rule.origin.exec(req.url))) ||
(_.isFunction(rule.origin) && rule.origin(req) ||
(_.isString(rule.origin) && _.isEqual(req.url, rule.origin)))
) {
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;
}
} else if (_.isString(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();
};
};