/** * 检测路由行为 * 通过自定义路由识别到对应的URL上 * @return {[type]} [description] */ var url = require("url"); var Dispatcher = think_require("Dispatcher"); module.exports = Behavior(function(){ return { options: { 'url_route_on': false, //是否开启自定义URL路由 'url_route_rules': [] //自定义URL路由规则 }, run: function(){ var pathname = this.http.pathname; if (!pathname || !this.options.url_route_on) { return false; }; var routes = this.options.url_route_rules; var length = routes.length; if (length === 0) { return false; }; for(var i = 0; i < length; i++){ var route = routes[i]; var rule = route[0]; //正则路由 if (rule && is_regexp(rule)) { var match = pathname.match(rule); if (match) { var result = this.parseRegExp(match, route[1], pathname); if (result) { return result; }; } continue; }; //字符串路由 var match = this.checkUrlMatch(pathname, rule); if (match) { return this.parseRule(rule, route[1], pathname); }; } return false; }, /** * 解析字符串路由 * @param {[type]} rule [description] * @param {[type]} route [description] * @param {[type]} pathname [description] * @return {[type]} [description] */ parseRule: function(rule, route, pathname){ route = this.getRoute(route); if (!route) { return false; }; pathname = pathname.split("/").filter(function(item){ return item.trim(); }); rule = rule.split("/").filter(function(item){ return item.trim(); }); var matches = {}; rule.forEach(function(item, i){ var pathitem = pathname.shift(); if (item.indexOf(":") === 0) { matches[item] = pathitem; } }); //将剩余的pathname分割为querystring if (pathname.length) { for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){ this.http.get[pathname[i * 2]] = pathname[i * 2 + 1] || ""; } }; var values = Object.values(matches); route = route.replace(/:(\d+)/g, function(a, b){ return values[b - 1] || ""; }); this.parseUrl(route); return true; }, /** * 检测URL是否匹配 * @param {[type]} pathname [description] * @param {[type]} rule [description] * @return {[type]} [description] */ checkUrlMatch: function(pathname, rule){ pathname = pathname.split("/").filter(function(item){ return item.trim(); }); rule = rule.split("/").filter(function(item){ return item.trim(); }); return rule.every(function(item, i){ if (item.indexOf(':') === 0) { if (item.indexOf('\\') > -1) { var type = item.substr(-1); if (type == 'd' && !is_number_string(pathname[i])) { return false; }; }; }else{ var pitem = pathname[i] || ""; if (pitem.toLowerCase() != item.toLowerCase()) { return false; }; } return true; }); }, /** * 解析转化后的url * @param {[type]} urlInfo [description] * @return {[type]} [description] */ parseUrl: function(urlInfo){ urlInfo = url.parse(urlInfo, true); if (urlInfo.query) { this.http.get = extend(this.http.get, urlInfo.query); }; var pathname = urlInfo.pathname || ""; // 过滤调用pathname最后有/的情况 pathname = pathname.split("/").filter(function(item){ return item.trim(); }); this.http.action = Dispatcher.getAction(pathname.pop()); this.http.controller = Dispatcher.getController(pathname.pop()); this.http.group = Dispatcher.getGroup(pathname.pop()); }, /** * 获取route * @param {[type]} route [description] * @return {[type]} [description] */ getRoute: function(route){ if (typeof route == 'function') { route = route(); }else if (is_object(route)) { var sRoute = ''; //对应的请求类型 for(var method in route){ var nmethod = method.split(",").filter(function(item){ return item.trim(); }); if (nmethod.indexOf(this.http.method) > -1) { sRoute = route[method]; break; }; } if (!sRoute) { return false; }; route = sRoute; }; return route; }, /** * 正则匹配路由 * @param {[type]} matches [description] * @param {[type]} route [description] * @param {[type]} pathname [description] * @return {[type]} [description] */ parseRegExp: function(matches, route, pathname){ route = this.getRoute(route); if (!route) { return false; }; route = route.replace(/:(\d+)/g, function(a, b){ return matches[b] || ""; }); pathname = pathname.replace(matches[0], ""); pathname = pathname.split("/").filter(function(item){ return item; }); //将剩余的pathname分割为querystring if (pathname.length) { for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){ this.http.get[pathname[i * 2]] = pathname[i * 2 + 1] || ""; } }; this.parseUrl(route); return true; } } });