thinkjs/lib/Lib/Behavior/CheckRouteBehavior.js
2014-06-28 07:55:31 +08:00

187 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 检测路由行为
* 通过自定义路由识别到对应的URL上
* @return {[type]} [description]
*/
var url = require('url');
var Dispatcher = thinkRequire('Dispatcher');
module.exports = Behavior(function(){
'use strict';
return {
options: {
'url_route_on': false, //是否开启自定义URL路由
'url_route_rules': [] //自定义URL路由规则
},
run: function(){
if (!this.options.url_route_on) {
return false;
}
var routes = this.options.url_route_rules;
var length = routes.length;
if (length === 0) {
return false;
}
var pathname = this.http.pathname;
var match;
for(var i = 0; i < length; i++){
var route = routes[i];
var rule = route[0];
//正则路由
if (isRegexp(rule)) {
match = pathname.match(rule);
if (match) {
var result = this.parseRegExp(match, route[1], pathname);
if (result) {
return result;
}
}
}else{
//字符串路由
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){
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' && !isNumberString(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) {
for(var key in urlInfo.query){
if (urlInfo.query[key] || !(key in this.http.get)) {
this.http.get[key] = urlInfo.query[key];
}
}
}
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 (isObject(route)) {
//对应的请求类型
for(var method in route){
//由于请求类型没有包含关系这里可以直接用indexOf判断
if (method.indexOf(this.http.method) > -1) {
return route[method];
}
}
return;
}
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;
}
};
});