Merge branch 'master' of github.com:welefen/thinkjs

This commit is contained in:
akira 2013-11-15 17:00:49 +08:00
commit 9362c8ab84
22 changed files with 441 additions and 182 deletions

View File

View File

@ -161,7 +161,11 @@ global.is_writable = function(p){
group && (mode & 00020) || // User is in group and group can write.
(mode & 00002); // Anyone can write.
}
/**
* 获取文件相关信息
* @param {[type]} file [description]
* @return {[type]} [description]
*/
global.file_state = function(file){
if (!fs.existsSync(file)) {
return false;
@ -180,7 +184,12 @@ global.file_get_contents = function(file){
var encoding = C("encoding") || "utf8";
return fs.readFileSync(file, encoding);
}
/**
* 设置文件内容
* @param {[type]} file [description]
* @param {[type]} data [description]
* @return {[type]} [description]
*/
global.file_put_contents = function(file, data){
return fs.writeFileSync(file, data);
}
@ -209,8 +218,6 @@ global.throw_error = function(obj, http){
};
throw new Error(JSON.stringify(obj));
}
/**
* 获取字符串的md5
* @param {[type]} str [description]
@ -220,4 +227,23 @@ global.md5 = function(str){
var instance = crypto.createHash('md5');
instance.update(str);
return instance.digest('hex');
}
/**
* 字符串命名风格转换
* @param {[type]} name [description]
* @param {[type]} type [description]
* @return {[type]} [description]
*/
global.parse_name = function(name, type){
name = (name + "").trim();
if (type == 1) {
name = name.replace(/_([a-zA-Z])/g, function(a, b){
return b.toUpperCase();
});
return name.substr(0, 1).toUpperCase() + name.substr(1);
} else {
return name.replace(/[A-Z]/g, function(a){
return "_" + a;
}).toLowerCase();
}
}

View File

@ -4,6 +4,7 @@
*/
var fs = require("fs");
var path = require("path");
var os = require("os");
var _alias = {};
@ -65,7 +66,7 @@ global.inherits = function(className, obj){
return cls;
};
["Cache", "Behavior", "Action", "Session", "Model", "Db"].forEach(function(item){
["Cache", "Behavior", "Controller", "Session", "Model", "Db"].forEach(function(item){
global[item] = function(obj){
return inherits(item, obj);
}
@ -152,14 +153,14 @@ global.C = function(name, value){
_config = extend(_config, name);
}
}
/**
* 记录时间和内存使用情况
*/
global.G = function(){
return {
time: Date.now(),
memory: os.totalmem() - os.freemem()
}
}
/**
* 实例化Action类可以调用一个具体的Action
@ -173,17 +174,17 @@ global.A = function(name, http, data){
name = name.split("/");
var gm = name.shift() + "/" + name.shift();
var action = name.shift();
var instance = think_require(gm + "Action")(http);
var instance = think_require(gm + "Controller")(http);
if (action) {
action += C('action_suffix');
return instance[action].apply(instance, data || []);
};
return instance;
}
/**
* 快速文件读取和写入
*/
var _cache = {};
global.F = function(name, value, rootPath){
if (rootPath === undefined) {
@ -213,12 +214,19 @@ global.F = function(name, value, rootPath){
};
return false;
}
global.M = function(){
}
global.D = function(){
/**
* 实例化模型
*/
global.M = global.D = function(name, tablePrefix, connection){
if (name === undefined) {
return think_require("Model")();
};
name = name.split(":");
try{
return think_require(name[0] + "Model")(name[1], tablePrefix, connection);
}catch(e){
return think_require("Model")(name[0], tablePrefix, connection);
}
}
/**
* 缓存
@ -247,6 +255,9 @@ global.S = function(name, value, options){
var expire = typeof options == 'number' ? options : undefined;
return instance.set(name, value, expire);
}
/**
* 计数
*/
global.N = function(){
}

View File

@ -57,7 +57,7 @@ function build_app_dir(){
COMMON_PATH, CACHE_PATH,
LOG_PATH, TEMP_PATH, DATA_PATH,
LIB_PATH + '/Model',
LIB_PATH + '/Action/Home',
LIB_PATH + '/Controller/Home',
LIB_PATH + '/Behavior',
LIB_PATH + '/Driver',
TMPL_PATH + "/Home"
@ -78,9 +78,9 @@ function build_app_dir(){
}
}
function build_first_action(){
var file = LIB_PATH + "/Action/Home/IndexAction.class.js";
var file = LIB_PATH + "/Controller/Home/IndexController.class.js";
if (!is_file(file)) {
var content = file_get_contents(THINK_PATH + "/Tpl/IndexAction.class.js");
var content = file_get_contents(THINK_PATH + "/Tpl/IndexController.class.js");
fs.writeFileSync(file, content);
};
}

View File

@ -3,7 +3,7 @@
* @type {Object}
*/
module.exports = {
"Action": THINK_LIB_PATH + "/Core/Action.class.js",
"Controller": THINK_LIB_PATH + "/Core/Controller.class.js",
"App": THINK_LIB_PATH + "/Core/App.class.js",
"Behavior": THINK_LIB_PATH + "/Core/Behavior.class.js",
"Cache": THINK_LIB_PATH + "/Core/Cache.class.js",

View File

@ -3,39 +3,38 @@
* @type {Object}
*/
module.exports = {
port: 8360, //监听的端口
port: 8360, //启动服务时用的端口
encoding: 'utf8', //编码
pathname_prefix: "", //不解析的pathname前缀
action_name_black_list: ["super", "init", /^\_[^\_]+/], //不能通过URL访问的action名单
app_tags_on: true, //是否支持标签功能
url_route_on: true, //开启自定义路由功能
use_php_vars: true, //使用PHP风格的变量$_GET, $_POST, $_FILES
post_data_asyn: false, //异步获取post数据
url_html_suffix: ".html", //url后缀
url_html_suffix: ".html", //url后缀这样可以做到伪静态对搜索引擎更友好
app_group_list: [], //分组列表
app_group_deny: [], //禁用分组列表
default_group: 'home', //默认分组
default_module: 'index', //默认模块
default_group: 'Home', //默认分组
default_controller: 'Index', //默认模块
default_action: 'index', //默认Action
url_module_map: {}, //Module别名,隐藏真实模块名
url_controller_map: {}, //Controller别名,隐藏真实模块名
url_action_map: {}, //Action别名
app_group_mode: 0, //0为普通分组1为独立分组
call_method: "__call", //当找不到方法时调用什么方法,这个方法存在时才有效
url_params_bind: true, //方法参数绑定,将URL参数值绑定到action的参数上
class_file_suffix: ".class.js", //类文件后缀
action_suffix: "Action", //action后缀
deny_ip: [], //阻止的ip
deny_remote_access_by_ip: true, //禁止通过外网的IP直接访问
url_callback_name: "callback", //jsonp格式的callback名字
json_content_type: "application/json",
cookie_domain: "", // Cookie有效域名
cookie_path: "", // Cookie路径
cookie_domain: "", //cookie有效域名
cookie_path: "", //cookie路径
cookie_expires: 0, //cookie默认保持时间数默认随浏览器关闭失效
cookie_prefix: "", // Cookie前缀 避免冲突
cookie_prefix: "", //cookie前缀,避免冲突
session_auto_start: true,
session_id: "thinkjs",
session_auto_start: true, //自动启动session
session_id: "thinkjs", //session id
session_type: "File", //session存储类型
session_options: {},
session_options: {}, //session的一些选项
session_cookie_sign: "", //session对应的cookie使用签名,如果使用这里填密钥
@ -59,14 +58,11 @@ module.exports = {
db_sql_log: false, // SQL执行日志记录
db_field_version: "", //
tpl_content_type: "text/html", //模版输出类型
tpl_file_suffix: ".html", //模版文件名后缀
tpl_file_depr: "_", //module和action之间的分隔符
tpl_file_depr: "_", //controller和action之间的分隔符
tpl_engine_type: "ejs", //模版引擎名称
tpl_engine_config: { //模版引擎需要的配置
},
tpl_engine_config: {}, //模版引擎需要的配置
log_record: false, //是否记录日志
@ -78,6 +74,6 @@ module.exports = {
data_path_level: 1, // 子目录缓存级别,默认不使用子目录
data_file_suffix: ".json", //缓存文件后缀
memcache_host: "127.0.0.1", //
memcache_host: "127.0.0.1", //memcache host
memcache_port: 11211, //memecache端口
};

View File

@ -13,7 +13,7 @@ module.exports = Behavior(function(){
'url_route_rules': {} //自定义URL路由规则
},
run: function(){
var pathname = this.http.req.pathname;
var pathname = this.http.pathname;
if (!pathname) {
return false;
};
@ -62,7 +62,7 @@ module.exports = Behavior(function(){
//将剩余的pathname分割为querystring
if (pathname.length) {
for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){
this.http.req.query[pathname[i * 2]] = pathname[i * 2 + 1] || "";
this.http.query[pathname[i * 2]] = pathname[i * 2 + 1] || "";
}
};
var values = [''];
@ -98,13 +98,13 @@ module.exports = Behavior(function(){
parseUrl: function(urlInfo){
urlInfo = url.parse(urlInfo, true);
if (urlInfo.query) {
this.http.req.query = extend(this.http.req.query, urlInfo.query);
this.http.query = extend(this.http.query, urlInfo.query);
};
var pathname = urlInfo.pathname || "";
pathname = pathname.split("/");
this.http.req.action = Dispatcher.getAction(pathname.pop() || "");
this.http.req.module = Dispatcher.getModule(pathname.pop() || "");
this.http.req.group = Dispatcher.getGroup(pathname.pop() || "");
this.http.action = Dispatcher.getAction(pathname.pop() || "");
this.http.controller = Dispatcher.getController(pathname.pop() || "");
this.http.group = Dispatcher.getGroup(pathname.pop() || "");
},
getRoute: function(route){
if (typeof route == 'function') {
@ -117,7 +117,7 @@ module.exports = Behavior(function(){
item = item.trim();
return item;
});
if (nmethod.indexOf(this.http.req.method) != -1) {
if (nmethod.indexOf(this.http.method) != -1) {
sRoute = route[method];
break;
};
@ -144,7 +144,7 @@ module.exports = Behavior(function(){
//将剩余的pathname分割为querystring
if (pathname.length) {
for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){
this.http.req.query[pathname[i * 2]] = pathname[i * 2 + 1] || "";
this.http.query[pathname[i * 2]] = pathname[i * 2 + 1] || "";
}
};
this.parseUrl(route);

View File

@ -11,7 +11,7 @@ module.exports = Behavior(function(){
if (this.options.deny_ip.length == 0) {
return true;
};
var clientIps = (this.http.req.ip+"").split(".");
var clientIps = (this.http.ip() + "").split(".");
var flag = this.options.deny_ip.some(function(item){
return (item + "").split(".").every(function(num, i){
if (num == "*" || num == clientIps[i]) {

View File

@ -14,27 +14,27 @@ module.exports = Behavior(function(){
templateFile = templateFile || "";
if (!templateFile) {
templateFile = [
TMPL_PATH, "/", this.http.req.group, "/",
this.http.req.module.toLowerCase(),
TMPL_PATH, "/", this.http.group, "/",
this.http.controller.toLowerCase(),
C('tpl_file_depr'),
this.http.req.action.toLowerCase(),
this.http.action.toLowerCase(),
C('tpl_file_suffix')
].join("");
}else if(templateFile.indexOf(C('tpl_file_suffix')) === -1){
var path = templateFile.split(":");
var action = path.pop();
var module = path.pop() || this.http.req.module.toLowerCase();
var group = ucfirst(path.pop()) || this.http.req.group;
var controller = path.pop() || this.http.controller.toLowerCase();
var group = ucfirst(path.pop()) || this.http.group;
templateFile = [
TMPL_PATH, "/", group, "/",
module,
controller,
C('tpl_file_depr'),
action,
C('tpl_file_suffix')
].join("");
}
if (!is_file(templateFile)) {
throw_error(templateFile + " is not exist");
throw_error(templateFile + " is not exist", this.http);
};
return templateFile;
}

View File

@ -7,7 +7,7 @@ module.exports = Behavior(function(){
run: function(data){
var content = data.content || data.file;
var engine = C('tpl_engine_type');
//不使用模版引擎
//不使用模版引擎,直接返回文件内容
if (!engine) {
return file_get_contents(content);
};

View File

@ -10,28 +10,32 @@ var App = module.exports = Class(function(){
this.http = http;
this.loadExtFile();
this.loadExtConfig();
//路径解析
think_require('Dispatcher')(http).run();
tag ('url_dispatch', http);
},
exec: function(){
var module = '';
var group = '';
var group = this.http.group;
var controller = '';
var self = this;
if (!(/^[A-Za-z](\w)*$/.test(this.http.req.module))) {
module = '';
//检测controller名
if (!(/^[A-Za-z](\w)*$/.test(this.http.controller))) {
controller = '';
}else{
group = this.http.req.group && C('app_group_mode') == 0 ? this.http.req.group + "/" : "";
try{
module = A(group + this.http.req.module, this.http);
controller = A(group + "/" + this.http.controller, this.http);
}catch(e){}
}
if (!module) {
module = A(group + "Empty", this.http);
if (!module) {
throw_error(this.http.req.module + " module not found", this.http);
if (!controller) {
try{
controller = A(group + "/" + "Empty", this.http);
}catch(e){}
if (!controller) {
throw_error(this.http.controller + " controller not found", this.http);
};
};
var action = this.http.req.action;
var action = this.http.action;
//添加action后缀
if (C('action_suffix')) {
action += C('action_suffix');
};
@ -49,12 +53,13 @@ var App = module.exports = Class(function(){
throw_error("action black", this.http);
};
};
//检测action名
if (!/^[A-Za-z](\w)*$/.test(action)) {
throw_error('action name error', this.http);
};
if (typeof module[action] == 'function') {
if (typeof controller[action] == 'function') {
if (C('url_params_bind')) {
var toString = module[action].toString();
var toString = controller[action].toString();
toString = toString.replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg, '');
var match = toString.match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1].split(/,/).filter(function(item){
return item;
@ -65,20 +70,20 @@ var App = module.exports = Class(function(){
var value = self.http.req.post[item] || self.http.req.query[item] || "";
data.push(value);
});
module[action].apply(module, data);
controller[action].apply(controller, data);
}else{
module[action]();
controller[action]();
}
}else{
module[action]();
controller[action]();
}
return true;
}else{
if (C('call_method') && typeof module[C('call_method')] == 'function') {
return module[C('call_method')](action);
if (C('call_method') && typeof controller[C('call_method')] == 'function') {
return controller[C('call_method')](action);
};
}
throw_error("action: "+action+" not found", this.http);
throw_error("action: " + action + " not found", this.http);
},
//加载自定义外部文件
loadExtFile: function(){
@ -115,8 +120,10 @@ var App = module.exports = Class(function(){
//start server
module.exports.run = function(){
var server = require("http").createServer(function (req, res) {
req.beginTime = Date.now();
var usage = G();
think_require("Http")(req, res).run(function(http){
http.setHeader("X-Powered-By", "thinkjs-" + THINK_VERSION);
http.usage = {"initApp": usage, "initHttp": G()};
//初始化Session
if (C('session_auto_start')) {
think_require('Session').start(http);
@ -124,7 +131,7 @@ module.exports.run = function(){
tag ('app_init', http);
var instance = App(http);
tag('app_begin', http);
G('initTime');
http.usage.appBegin = G();
instance.exec();
tag('app_end', http);
});

View File

@ -1,5 +1,5 @@
/**
* Action基类
* Controller基类
* @return {[type]} [description]
*/
var fs = require("fs");
@ -8,6 +8,8 @@ module.exports = Class(function(){
init: function(http){
this.http = http;
this.view = null;
//将http数据打到模版里
this.assign("http", this.http);
tag('action_start');
},
/**
@ -15,7 +17,7 @@ module.exports = Class(function(){
* @return {[type]} [description]
*/
ip: function(){
return this.http.req.ip;
return this.http.ip();
},
/**
* 实例化View类
@ -32,14 +34,14 @@ module.exports = Class(function(){
* @return {Boolean} [description]
*/
isGet: function(){
return this.http.req.method == 'get';
return this.http.method == 'get';
},
/**
* 是否是POST请求
* @return {Boolean} [description]
*/
isPost: function(){
return this.http.req.method == 'post';
return this.http.method == 'post';
},
/**
* 是否是特定METHOD请求
@ -47,7 +49,7 @@ module.exports = Class(function(){
* @return {Boolean} [description]
*/
isMethod: function(method){
return this.http.req.method == method;
return this.http.method == method;
},
/**
* 是否是AJAX请求
@ -62,7 +64,10 @@ module.exports = Class(function(){
* @return {[type]} [description]
*/
get: function(name){
return this.http.req.query[name] || "";
if (name === undefined) {
return this.http.query;
};
return this.http.query[name] || "";
},
/**
* 获取POST参数
@ -70,13 +75,26 @@ module.exports = Class(function(){
* @return {[type]} [description]
*/
post: function(name){
return this.http.req.post[name] || "";
if (name === undefined) {
return this.http.post;
};
return this.http.post[name] || "";
},
/**
* 获取参数
* @param {[type]} name [description]
* @return {[type]} [description]
*/
param: function(name){
return this.post(name) || this.get(name);
},
/**
* 获取上传的文件
* @param {[type]} name [description]
* @return {[type]} [description]
*/
file: function(name){
return this.http.req.file[name] || "";
return this.http.file[name] || "";
},
/**
* header操作
@ -86,13 +104,13 @@ module.exports = Class(function(){
*/
header: function(name, value){
if (value !== undefined) {
this.http.res.setHeader(name, value);
this.http.setHeader(name, value);
return this;
};
if (name === undefined) {
return this.http.req.headers;
return this.http.headers;
};
return this.http.req.getHeader(name);
return this.http.getHeader(name);
},
/**
* cookie操作
@ -103,13 +121,13 @@ module.exports = Class(function(){
*/
cookie: function(name, value, options){
if (value !== undefined) {
this.http.res.setCookie(name, value, options);
this.http.setCookie(name, value, options);
return this;
};
if (name === undefined) {
return this.http.req.cookie;
return this.http.cookie;
};
return this.http.req.cookie[name];
return this.http.cookie[name];
},
/**
* session
@ -120,7 +138,7 @@ module.exports = Class(function(){
*/
session: function(name, value){
think_require('Session').start(this.http);
var instance = this.http.req.session;
var instance = this.http.session;
if (name === undefined) {
return instance.rm();
};
@ -130,13 +148,18 @@ module.exports = Class(function(){
};
return instance.get(name);
},
/**
* 跳转
* @param {[type]} url [description]
* @param {[type]} code [description]
* @return {[type]} [description]
*/
redirect: function(url, code){
throw_error({
type: "redirect",
msg: url,
code: code,
http: this.http
});
}, this.http);
},
/**
* 赋值变量到模版
@ -168,17 +191,42 @@ module.exports = Class(function(){
display: function(templateFile, charset, contentType, content){
return this.initView().display(templateFile, charset, contentType, content);
},
/**
* 输出错误
* @param {[type]} msg [description]
* @return {[type]} [description]
*/
error: function(msg){
throw_error(msg, this.http);
},
/**
* [action description]
* 调用另一个controll里的aciton
* 可以跨分组
* A("Home/Test/index")
* @param {[type]} action [description]
* @return {[type]} [description]
*/
action: function(action){
A(action, this.http);
},
/**
* json格式输出并且支持jsonp的方式
* @param {[type]} data [description]
* @param {[type]} jsonp [description]
* @return {[type]} [description]
*/
json: function(data, jsonp){
this.header("Content-Type", C("json_content_type"));
var callback = this.get(C("url_callback_name"));
callback = callback.replace(/[^\w\.]/g, "");
if (jsonp && callback) {
this.echo(callback + "(");
this.echo(data);
this.end(")");
}else{
this.end(data);
}
},
/**
* 输出内容
* 自动JSON.stringify
@ -193,7 +241,7 @@ module.exports = Class(function(){
if (!is_string(obj) && !(obj instanceof Buffer)) {
obj += "";
};
this.http._res.write(obj, encoding || C('encoding'));
this.http.res.write(obj, encoding || C('encoding'));
},
/**
* 结束输出输出完成时一定要调用这个方法
@ -204,7 +252,7 @@ module.exports = Class(function(){
if (obj) {
this.echo(obj);
};
this.http.res.end();
this.http.end();
},
/**
* 下载文件
@ -215,12 +263,12 @@ module.exports = Class(function(){
var mime = require('mime');
contentType = mime.lookup(file);
};
var res = this.http.res;
var http = this.http;
var fileStream = fs.createReadStream(file);
res.setHeader("Content-Type", contentType);
fileStream.pipe(res);
http.setHeader("Content-Type", contentType);
fileStream.pipe(http.res);
fileStream.on("end", function(){
res.end();
http.end();
})
},
/**

View File

@ -78,14 +78,14 @@ var db = module.exports = Class(function(){
return this.parseDSN(C('db_dsn'));
};
return {
'dbms' => C('db_type'),
'username' => C('db_user'),
'password' => C('db_pwd'),
'hostname' => C('db_host'),
'hostport' => C('db_port'),
'database' => C('db_name'),
'dsn' => C('db_dsn'),
'params' => C('db_params'),
'dbms' : C('db_type'),
'username' : C('db_user'),
'password' : C('db_pwd'),
'hostname' : C('db_host'),
'hostport' : C('db_port'),
'database' : C('db_name'),
'dsn' : C('db_dsn'),
'params' : C('db_params'),
}
}
return config;

View File

@ -7,17 +7,17 @@ var path = require("path");
var Dispatcher = module.exports = Class(function(){
return {
http: null,
init: function(http){
this.http = http;
},
run: function(){
var _group = "";
var _module = "";
var _action = "";
var group = "";
var controller = "";
var action = "";
tag("path_info", this.http);
var pathname = this.http.req.pathname;
var pathname = this.http.pathname;
var extname = path.extname(pathname);
//判断URL后缀
if (extname == C('url_html_suffix')) {
pathname = path.dirname(pathname) + "/" + path.basename(pathname, C('url_html_suffix'));
};
@ -31,9 +31,9 @@ var Dispatcher = module.exports = Class(function(){
if (C('pathname_prefix') && pathname.indexOf(C('pathname_prefix')) === 0) {
pathname = pathname.substr(C('pathname_prefix').length);
};
this.http.req.pathname = pathname;
this.http.pathname = pathname;
if (pathname == 'favicon.ico') {
throw_error("favicon.ico");
throw_error("favicon.ico", this.http);
return false;
};
if (!this.routerCheck()) {
@ -41,25 +41,25 @@ var Dispatcher = module.exports = Class(function(){
var groupList = C('app_group_list') || [];
if (groupList.length) {
if (groupList.indexOf(paths[0])) {
_group = paths.shift();
group = paths.shift();
};
};
var deny = C('app_group_deny') || [];
if (_group && deny.length) {
if (group && deny.length) {
if (deny.indexOf(_group)) {
throw new Error("");
throw_error("favicon.ico", this.http);
};
};
_module = paths.shift();
_action = paths.shift();
controller = paths.shift();
action = paths.shift();
if (paths.length) {
for(var i = 0,length = Math.ceil(paths.length)/2; i < length; i++){
this.http.req.query[paths[i*2]] = paths[i*2+1] || "";
this.http.query[paths[i * 2]] = paths[i * 2 + 1] || "";
}
};
this.http.req.group = Dispatcher.getGroup(_group);
this.http.req.module = Dispatcher.getModule(_module);
this.http.req.action = Dispatcher.getAction(_action);
this.http.group = Dispatcher.getGroup(group);
this.http.controller = Dispatcher.getController(controller);
this.http.action = Dispatcher.getAction(action);
};
return true;
},
@ -68,14 +68,23 @@ var Dispatcher = module.exports = Class(function(){
}
}
});
Dispatcher.getModule = function(module){
module = module || C('default_module');
if (C('url_module_map')[module]) {
return C('url_module_map')[module];
/**
* 获取controller
* @param {[type]} controller [description]
* @return {[type]} [description]
*/
Dispatcher.getController = function(controller){
controller = controller || C('default_controller');
if (C('url_controller_map')[controller]) {
return C('url_controller_map')[controller];
};
return ucfirst(module);
return ucfirst(controller);
};
/**
* 获取action
* @param {[type]} action [description]
* @return {[type]} [description]
*/
Dispatcher.getAction = function(action){
action = action || C('default_action');
if (C('url_action_map')[action]) {
@ -83,6 +92,11 @@ Dispatcher.getAction = function(action){
};
return action;
};
/**
* 获取group
* @param {[type]} group [description]
* @return {[type]} [description]
*/
Dispatcher.getGroup = function(group){
group = group || C('default_group');
return ucfirst(group);

View File

@ -22,7 +22,7 @@ module.exports = Class(function(){
this._response();
var method = this.req.method;
var methods = ["post", "put", "patch"];
if (methods.indexOf(method)> -1) {
if (methods.indexOf(method) > -1) {
this.getData(callback);
}else{
callback && callback(this.http);
@ -39,10 +39,10 @@ module.exports = Class(function(){
var form = new multiparty.Form();
var self = this;
form.on("file", function(name, value){
self.http.req.file[name] = value;
self.http.file[name] = value;
});
form.on("field", function(name, value){
self.http.req.post[name] = value;
self.http.post[name] = value;
});
form.on("close", function(){
callback && callback(self.http);
@ -50,10 +50,9 @@ module.exports = Class(function(){
form.parse(this.req);
},
_request: function(){
var self = this;
var req = {
version: this.req.httpVersion,
statusCode: this.req.statusCode,
status: http.STATUS_CODES[this.req.statusCode] || "",
method: this.req.method.toLowerCase(),
headers: this.req.headers,
getHeader: function(name){
@ -64,23 +63,32 @@ module.exports = Class(function(){
},
post: {},
file: {},
ip: this.req.headers["x-real-ip"] || this.req.headers["x-forwarded-for"]
ip: function(){
return this.headers["x-real-ip"]
|| this.headers["x-forwarded-for"]
|| this.req.connection.remoteAddress
|| this.req.socket.remoteAddress
|| this.req.connection.socket.remoteAddress;
}
};
//cookie
req.cookie = cookie.parse(this.req.headers.cookie || "");
var urlInfo = url.parse(this.req.url, true);
extend(req, urlInfo);
this.http.req = req;
this.http.beginTime = this.req.beginTime;
this.http._req = this.req;
extend(this.http, req);
//解析url中的参数
var urlInfo = url.parse("//" + req.headers.host + this.req.url, true, true);
this.http.pathname = urlInfo.pathname;
this.http.query = urlInfo.query;
this.http.get = urlInfo.get;
this.http.host = urlInfo.host;
this.http.hostname = urlInfo.hostname;
this.http.req = this.req;
},
_response: function(){
var self = this;
var res = {
setHeader: function(name, value){
self.res.setHeader(name, value);
this.res.setHeader(name, value);
},
setCookie: function(name, value, options){
options = options || {};
@ -110,16 +118,14 @@ module.exports = Class(function(){
this.setHeader("Set-Cookie", value);
},
end: function(){
tag("before_res_end", self.http);
tag("before_res_end", this);
//end前保存session
if (self.http.req.session) {
self.http.req.session.flush();
};
self.http._res.end();
this.session && this.session.flush();
this.res.end();
}
}
this.http.res = res;
this.http._res = this.res;
extend(this.http, res);
this.http.res = this.res;
}
}
});

View File

@ -32,7 +32,7 @@ var model = module.exports = Class(function(){
this.name = "";
// 数据库名称
this.dbName = "";
//数据库配置
// 数据库配置
this.connection = "";
// 数据表名(不包含表前缀)
this.tableName = "";
@ -40,9 +40,9 @@ var model = module.exports = Class(function(){
this.trueTableName = "";
// 最近错误信息
this.error = "";
//字段信息
// 字段信息
this.fields = [];
//数据信息
// 数据信息
this.data = [];
// 查询表达式参数
this.options = [];
@ -60,9 +60,13 @@ var model = module.exports = Class(function(){
this.patchValidate = false;
// 链操作方法列表
this.methods = ['table','order','alias','having','group','lock','distinct','auto','filter','validate'];
//deferred
// deferred
this.deferred = when.defer();
},
/**
* 重置promise
* @return {[type]} [description]
*/
resetDeferred: function(){
this.deferred.reject();
this.deferred = when.defer();
@ -101,7 +105,7 @@ var model = module.exports = Class(function(){
this.initDb(0, connection || this.connection);
},
/**
* 得到当前的数据对象名称
* 获取模型名
* @access public
* @return string
*/
@ -113,6 +117,22 @@ var model = module.exports = Class(function(){
};
return this.name;
},
/**
* 获取表名
* @return {[type]} [description]
*/
getTableName: function(){
if (!this.trueTableName) {
var tableName = this.tablePrefix || "";
if (this.tableName) {
tableName += this.tableName;
}else{
tableName += parse_name(this.name);
}
this.trueTableName = tableName.toLowerCase();
};
return (this.dbName ? this.dbName + "." : "") + this.trueTableName;
},
/**
* 初始化数据库连接
* @access public
@ -173,6 +193,7 @@ var model = module.exports = Class(function(){
// 每次都会读取数据表信息
this.flush();
},
flush: function(){
// 缓存不存在则查询数据表信息
@ -181,6 +202,118 @@ var model = module.exports = Class(function(){
data = data || "";
options = options || [];
replace = replace || false;
},
getLastSql: function(){
return this.db.getLastSql();
},
/**
* 获取主键名称
* @access public
* @return string
*/
getPk: function(){
return this.fields['_pk'] || this.pk;
},
/**
* 缓存
* @param {[type]} key [description]
* @param {[type]} expire [description]
* @param {[type]} type [description]
* @return {[type]} [description]
*/
cache: function(key, expire, type){
this.options.cache = {
key: key,
expire: expire,
type: type
};
return this;
},
/**
* 指定查询数量
* @param {[type]} offset [description]
* @param {[type]} length [description]
* @return {[type]} [description]
*/
limit: function(offset, length){
this.options.limit = length === undefined ? offset : offset + "," + length;
return this;
},
/**
* 指定分页
* @return {[type]} [description]
*/
page: function(page, listRows){
this.options.page = listRows === undefined ? page : page + "," + listRows;
return this;
},
/**
* where条件
* @return {[type]} [description]
*/
where: function(where){
if (is_string(where)) {
where = {
_string: where
}
};
if (this.options.where) {
this.options.where = extend(this.options.where, where);
}else{
this.options.where = where;
}
return this;
},
/**
* 要查询的字段
* @return {[type]} [description]
*/
field: function(field){
if (field === true) {
field = this.getDbField() || "*";
};
this.options.field = field;
return this;
},
/**
* 联合查询
* @return {[type]} [description]
*/
union: function(union){
if (!this.options.union) {
this.options.union = [];
};
this.options.union.push(union);
return this;
},
join: function(join){
if (is_array(join)) {
this.options.join = join;
}else{
if (!this.options.join) {
this.options.join = [];
};
this.options.join.push(join);
}
return this;
},
getError: function(){
return this.error;
},
rollback: function(){
return this.db.rollback();
},
commit: function(){
return this.db.commit();
},
startTrans: function(){
this.commit();
this.db.startTrans();
return this;
},
parseOptions: function(options){
options = extend(this.options, options);
this.options = {};
}
}

View File

@ -22,7 +22,7 @@ module.exports = Class(function(){
cookie: null,
init: function(http){
this.http = http;
this.cookie = this.http.req.session_cookie;
this.cookie = this.http.session_cookie;
},
get: function(name){
var deferrd = when.defer();
@ -39,12 +39,13 @@ module.exports = Class(function(){
//解析cookie
module.exports.start = function(http){
if (http.req.session_cookie) {
return http.req.session_cookie;
if (http.session_cookie) {
return http.session_cookie;
};
var name = C('session_id');
//是否使用签名
var secret = C('session_cookie_sign');
var cookie = http.req.cookie[name];
var cookie = http.cookie[name];
if (cookie && secret) {
cookie = cookie_unsign(cookie, secret);
};
@ -53,13 +54,15 @@ module.exports.start = function(http){
if (secret) {
cookie = cookie_sign(cookie, secret);
};
http.res.setCookie(name, cookie, C('session_options'));
http.setCookie(name, cookie, C('session_options'));
}
http.req.session_cookie = cookie;
//将cookie值放到http对象上方便后续获取
http.session_cookie = cookie;
var name = C('session_type') + "Session";
var cls = think_require(name)(http);
http.req.session = cls;
//session类
http.session = cls;
return cookie;
};

View File

@ -5,35 +5,42 @@
module.exports = {
start: function(){
this.register_exception();
//think_require的autoload
register_autoload(this.autoload);
this.buildApp();
think_require('App').run();
},
/**
* 注册异常处理
* @return {[type]} [description]
*/
register_exception: function(){
process.on('uncaughtException', function(err) {
if (typeof err && err.http) {
if (err && err.http) {
var http = err.http;
switch(err.type){
case "deny":
http._res.statusCode = err.code || 403;
http._res.write(err.msg, C('encoding'));
http.res.statusCode = err.code || 403;
http.res.write(err.msg, C('encoding'));
break;
case "redirect":
http._res.statusCode = err.code || 302;
http._res.setHeader("Location", err.msg);
http.res.statusCode = err.code || 302;
http.res.setHeader("Location", err.msg);
break;
default:
http._res.statusCode = err.code || 500;
http._res.write(err.msg, C('encoding'));
http.res.statusCode = err.code || 500;
http.res.write(err.msg, C('encoding'));
}
err.http.res.end();
err.http.end();
return;
};
console.log(err);
});
},
buildApp: function(){
//加载系统默认配置
C(require(THINK_PATH + '/Conf/convention.js'));
//加载用户配置
var file = CONF_PATH + '/config.js';
if (is_file(file)) {
C(require(file));
@ -44,8 +51,15 @@ module.exports = {
C("url_route_rules", require(CONF_PATH + "/route.js"));
};
};
//加载行为配置
if (C('app_tags_on')) {
//加载系统行为配置
C('sys_tags', require(THINK_PATH + "/Conf/tags.js"));
//加载用户的行为配置
var tagFile = COMMON_PATH + "/tags.js";
if (is_file(tagFile)) {
C('tags', require(tagFile));
};
};
//common文件
if (is_file(COMMON_PATH + "/common.js")) {
@ -61,6 +75,7 @@ module.exports = {
if (is_file(THINK_PATH + "/Conf/debug.js")) {
C(require(THINK_PATH + "/Conf/debug.js"));
};
//debug下自定义状态的配置
var status = C('app_status');
if (status && is_file(CONF_PATH + "/" + status + '.js')) {
C(require(CONF_PATH + "/" + status + ".js"));
@ -85,8 +100,8 @@ module.exports = {
Model: [
LIB_PATH + "/Model/" + file
],
Action: [
LIB_PATH + "/Action/" + file
Controller: [
LIB_PATH + "/Controller/" + file
],
Cache: [
LIB_PATH + "/Driver/Cache/" + file,

View File

@ -36,9 +36,8 @@ module.exports = Class(function(){
if (contentType === undefined) {
contentType = C('tpl_content_type');
};
this.http.res.setHeader("Content-Type", contentType + "; charset="+charset);
this.http.res.setHeader("X-Powered-By", "thinkjs");
this.http._res.write(content || "", C('encoding'));
this.http.setHeader("Content-Type", contentType + "; charset="+charset);
this.http.res.write(content || "", C('encoding'));
},
fetch: function(templateFile, content){
if (content === undefined) {

View File

@ -1,8 +1,8 @@
/**
* action
* controller
* @return
*/
module.exports = Action(function(){
module.exports = Controller(function(){
return {
/*init: function(){
this.super("init");

View File

@ -12,5 +12,6 @@ if (!global.RUNTIME_PATH) {
if (global.APP_DEBUG === undefined) {
global.APP_DEBUG = false;
};
global.THINK_VERSION = "0.1.4";
global.THINK_PATH = __dirname;
require(THINK_PATH + "/Common/runtime.js");

View File

@ -1,7 +1,7 @@
{
"name": "thinkjs",
"description": "thinkphp web framework for nodejs",
"version": "0.1.1",
"version": "0.1.4",
"author": {
"name": "welefen",
"email": "welefen@gmail.com"