| 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 | 1
1
1
1
1
1
1
34
10
10
34
34
34
34
3
31
31
31
3
28
28
15
13
13
7
1
8
1
7
7
1
6
6
6
6
6
6
1
6
1
20
20
20
2
2
1
1
20
1
19
19
19
2
19
19
1
18
10
8
19
19
6
6
19
1
8
8
8
8
8
2
6
6
7
1
10
10
4
4
4
1
3
4
4
6
6
6
4
6
6
6
6
1
6
1
5
5
5
2
3
3
3
1
2
2
1
1
1
2
1
1
1
1
1
2
2
2
1
6
6
3
1
2
1
4
3
4
4
4
1
1
7
4
1
1
1
3
3
3
3
3
3
3
3
3
2
1
2
3
| var cluster = require('cluster');
var fs = require('fs');
var domain = require('domain');
var thinkHttp = thinkRequire('Http');
var Dispatcher = thinkRequire('Dispatcher');
var App = module.exports = {};
/**
* 根据http里的group和controller获取对应的controller实例
* @param {[type]} http [description]
* @return {[type]} [description]
*/
App.getBaseController = function(http, options, checkAction){
'use strict';
if (options === true) {
checkAction = true;
options = {};
}
options = options || {};
var group = options.group || http.group;
var controller = options.controller || http.controller;
if (!controller) {
return;
}
var gc = ucfirst(group) + '/' + ucfirst(controller) + 'Controller';
var path = getThinkRequirePath(gc);
if (!path) {
return;
}
var instance = require(path)(http);
if (!checkAction) {
return instance;
}
var action = options.action || http.action;
//action对应的方法或者call方法存在
if (isFunction(instance[action + C('action_suffix')]) || isFunction(instance[C('call_method')])) {
return instance;
}
}
/**
* controller不存在时调用的默认controller
* @return {[type]} [description]
*/
App.getCallController = function(http){
'use strict';
//如果是RESTFUL API,则调用RestController
if (http.isRestful) {
return thinkRequire('RestController')(http);
}
var config = C('call_controller');
if (!config) {
return;
}
config = config.split(':');
var action = Dispatcher.getAction(config.pop());
var controller = Dispatcher.getController(config.pop());
var group = Dispatcher.getGroup(config.pop());
var instance = this.getBaseController(http, {
group: group,
controller: controller,
action: action
}, true);
if (instance) {
http._action = action;
}
return instance;
}
/**
* 执行具体的action,调用前置和后置操作
* @return {[type]} [description]
*/
App.execAction = function(controller, action, data, callMethod){
'use strict';
//action操作
var act = action + C('action_suffix');
var flag = false;
//action不存在时执行魔术方法
if (callMethod && !isFunction(controller[act])) {
var call = C('call_method');
if (call && isFunction(controller[call])) {
flag = true;
act = call;
}
}
//action不存在
if (!isFunction(controller[act])) {
return getPromise(new Error('action `' + action + '` not found.'), true);
}
var promise = getPromise();
//action前置操作
var before = C('before_action');
if (before && isFunction(controller[before])) {
promise = getPromise(controller[before](action));
}
promise = promise.then(function(){
//action魔术方法只传递action参数
if (flag) {
return controller[act](action);
}
if (data) {
return controller[act].apply(controller, data);
}else{
return controller[act]();
}
});
//action后置操作
var after = C('after_action');
if (after && isFunction(controller[after])) {
promise = promise.then(function(){
return controller[after](action);
})
}
return promise;
}
/**
* 获取action的形参
* @return {[type]} [description]
*/
App.getActionParams = function(fn, http){
'use strict';
//注释的正则
var commentReg = /((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg;
//获取形参的正则
var parsReg = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var toString = fn.toString().replace(commentReg, '');
var match = toString.match(parsReg)[1];
if (!match) {
return [];
}
match = match.split(/\s*,\s*/);
//匹配到形参
return match.map(function(item){
return http.post[item] || http.get[item] || '';
});
}
/**
* 执行
* @param {[type]} http [description]
* @return {[type]} [description]
*/
App.exec = function(http){
'use strict';
var controller = this.getBaseController(http, true) || this.getCallController(http, true);
//controller或者action不存在
if (!controller) {
var path = getThinkRequirePath(ucfirst(http.group) + '/' + ucfirst(http.controller) + 'Controller');
var cmessage;
if (path) {
cmessage = 'action `' + http.action + '` not found.';
}else{
cmessage = 'Controller' + (http.controller ? ' `' + http.controller + '`' : '') + ' not found.';
}
var err = new Error(cmessage + ' pathname is `' + http.pathname + '`');
return getPromise(err, true);
}
//controller类实例
//http.controllerInstance = controller;
var params;
var actionFn = controller[http.action + C('action_suffix')];
//参数绑定
if (C('url_params_bind')) {
params = this.getActionParams(actionFn, http);
}
var promise = getPromise(controller.__initReturn);
var self = this;
return promise.then(function(){
return self.execAction(controller, http._action || http.action, params, true);
})
}
/**
* 发送错误信息
* @param {[type]} error [description]
* @return {[type]} [description]
*/
App.sendError = function(http, error){
'use strict';
if (!error) {
return;
}
var message = isError(error) ? error.stack : error;
console.error(message);
if (!http.res) {
return;
}
http.res.statusCode = 500;
http.setHeader('Content-Type', 'text/html; charset=' + C('encoding'));
if (APP_DEBUG) {
http.res.end(message);
}else{
var readStream = fs.createReadStream(C('error_tpl_path'));
readStream.pipe(http.res);
readStream.on('end', function(){
http.res.end();
});
}
}
/**
* run
* @return {[type]} [description]
*/
App.run = function(){
'use strict';
if (APP_MODE && App.mode[APP_MODE]) {
return App.mode[APP_MODE]();
}
return App.mode.http();
};
/**
* 不同模式下的run
* @type {Object}
*/
App.mode = {
//命令行模式
cli: function(){
'use strict';
var defaultHttp = thinkHttp.getDefaultHttp(process.argv[2]);
thinkHttp(defaultHttp.req, defaultHttp.res).run().then(App.listener);
},
//HTTP模式
http: function(){
'use strict';
var clusterNums = C('use_cluster');
//不使用cluster
Eif (!clusterNums) {
return App.createServer();
}
//使用cpu的个数
if (clusterNums === true) {
clusterNums = require('os').cpus().length;
}
if (cluster.isMaster) {
for (var i = 0; i < clusterNums; i++) {
cluster.fork();
}
cluster.on('exit', function(worker) {
console.error('worker ' + worker.process.pid + ' died');
process.nextTick(function(){
cluster.fork();
});
});
}else {
App.createServer();
}
}
};
/**
* 创建服务
* @return {[type]} [description]
*/
App.createServer = function(){
'use strict';
//自定义创建server
var createServerFn = C('create_server_fn');
if (createServerFn) {
if (isFunction(createServerFn)) {
return createServerFn(App);
}else if (isFunction(global[createServerFn])) {
return global[createServerFn](App);
}
}
var server = require('http').createServer(function (req, res) {
thinkHttp(req, res).run().then(App.listener);
});
thinkRequire('WebSocket')(server, App).run();
server.listen(C('port'));
if (APP_DEBUG) {
console.log('Server running at http://127.0.0.1:' + C('port') + '/');
}
}
/**
* 监听回调函数
* @param {[type]} http [description]
* @return {[type]} [description]
*/
App.listener = function(http){
'use strict';
//自动发送thinkjs和版本的header
http.setHeader('X-Powered-By', 'thinkjs-' + THINK_VERSION);
//禁止远程直接用带端口的访问,websocket下允许
if (C('use_proxy') && http.host !== http.hostname && !http.websocket) {
http.res.statusCode = 403;
http.res.end();
return getDefer().promise;
}
var domainInstance = domain.create();
var deferred = getDefer();
domainInstance.on('error', function(err){
App.sendError(http, err);
deferred.reject(err);
});
domainInstance.run(function(){
return tag('app_init', http).then(function(){
return Dispatcher(http).run();
}).then(function(){
return tag('app_begin', http);
}).then(function(){
return tag('action_init', http);
}).then(function(){
return App.exec(http);
}).then(function(){
return tag('app_end', http);
}).catch(function(err){
App.sendError(http, err);
}).then(function(){
deferred.resolve();
})
});
return deferred.promise;
}; |