total5 0.0.1-9 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.js +18 -10
- package/bin/flow5 +142 -0
- package/bin/total5 +166 -905
- package/builders.js +90 -35
- package/changelog.txt +3 -1
- package/cluster.js +1 -1
- package/cms.js +185 -51
- package/controller.js +233 -70
- package/cron.js +1 -1
- package/debug.js +12 -5
- package/edit.js +26 -33
- package/filestorage.js +38 -17
- package/flow-flowstream.js +199 -68
- package/flow.js +16 -10
- package/flowstream.js +4 -3
- package/global.js +84 -1
- package/htmlparser.js +41 -29
- package/http.js +3 -1
- package/image.js +4 -0
- package/images.js +1 -1
- package/index.js +246 -117
- package/jsonschema.js +21 -17
- package/macros.js +222 -0
- package/mail.js +11 -27
- package/markdown.js +21 -11
- package/minificators.js +1 -1
- package/nosql-querybuilder.js +4 -0
- package/nosql.js +8 -0
- package/openclient.js +1 -1
- package/package.json +4 -3
- package/pause.html +1 -1
- package/release.js +1 -1
- package/routing.js +118 -35
- package/sourcemap.js +6 -3
- package/test.js +9 -2
- package/tms.js +11 -14
- package/uibuilder.js +59 -23
- package/utils.js +147 -102
- package/viewengine.js +19 -8
- package/websocket.js +10 -6
- package/503.html +0 -65
- package/CONTRIBUTING.md +0 -55
- package/helpers/index.js +0 -32
- package/templates.json +0 -74
- package/tests/bundles/index.js +0 -25
- package/tests/cron.js +0 -0
- package/tests/htmlparser.js +0 -0
- package/tests/minifactors.js +0 -17
- package/tests/nosql.js +0 -18
- package/tests/proxy/index.js +0 -21
- package/tests/routing/index.js +0 -27
- package/tests/schemas.js +0 -17
- package/tests/server/index.js +0 -24
- package/tests/staticfiles/index.js +0 -24
- package/tests/utils.js +0 -17
- package/tmsclient.js +0 -125
- package/todo.txt +0 -11
- package/tools/beta.sh +0 -6
- package/tools/release.sh +0 -6
package/controller.js
CHANGED
|
@@ -11,17 +11,23 @@ const REG_MOBILE = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Min
|
|
|
11
11
|
const REG_ENCODINGCLEANER = /[;\s]charset=utf-8/g;
|
|
12
12
|
|
|
13
13
|
const CHECK_DATA = { POST: 1, PUT: 1, PATCH: 1, DELETE: 1 };
|
|
14
|
-
const CHECK_COMPRESSION = { 'text/plain': true, 'text/javascript': true, 'text/css': true, 'text/jsx': true, 'application/javascript': true, 'application/x-javascript': true, 'application/json': true, 'application/xml': true, 'text/xml': true, 'image/svg+xml': true, 'text/x-markdown': true, 'text/html': true };
|
|
15
|
-
const CHECK_CHARSET = { 'text/plain': true, 'text/javascript': true, 'text/css': true, 'text/jsx': true, 'application/javascript': true, 'application/x-javascript': true, 'application/json': true, 'text/xml': true, 'text/x-markdown': true, 'text/html': true };
|
|
14
|
+
const CHECK_COMPRESSION = { 'text/plain': true, 'text/javascript': true, 'text/css': true, 'text/jsx': true, 'application/javascript': true, 'application/x-javascript': true, 'application/json': true, 'application/xml': true, 'text/xml': true, 'image/svg+xml': true, 'text/x-markdown': true, 'text/html': true, 'application/x-ipynb+json': true, 'application/x-ijsnb+json': true };
|
|
15
|
+
const CHECK_CHARSET = { 'text/plain': true, 'text/javascript': true, 'text/css': true, 'text/jsx': true, 'application/javascript': true, 'application/x-javascript': true, 'application/json': true, 'text/xml': true, 'text/x-markdown': true, 'text/html': true, 'application/x-ijsnb+json': true, 'application/x-ipynb+json': true };
|
|
16
16
|
const CHECK_NOCACHE = { zip: 1, rar: 1 };
|
|
17
|
+
const CHECK_MIN = /(\.|-|@)min/i;
|
|
17
18
|
|
|
18
19
|
const GZIP_FILE = { memLevel: 9 };
|
|
19
20
|
const GZIP_STREAM = { memLevel: 1 };
|
|
20
21
|
|
|
22
|
+
const NOCACHE = 'private, no-cache, no-store, max-age=0';
|
|
23
|
+
|
|
21
24
|
function Controller(req, res) {
|
|
22
25
|
|
|
23
26
|
var ctrl = this;
|
|
24
27
|
|
|
28
|
+
req.controller = ctrl;
|
|
29
|
+
|
|
30
|
+
ctrl.timeout = F.config.$httptimeout;
|
|
25
31
|
ctrl.req = req;
|
|
26
32
|
ctrl.res = res;
|
|
27
33
|
ctrl.method = ctrl.req.method;
|
|
@@ -58,7 +64,7 @@ function Controller(req, res) {
|
|
|
58
64
|
|
|
59
65
|
ctrl.response = {
|
|
60
66
|
status: 200,
|
|
61
|
-
cache: DEBUG,
|
|
67
|
+
cache: global.DEBUG != true,
|
|
62
68
|
minify: true,
|
|
63
69
|
// minifyjson: false
|
|
64
70
|
// encrypt: false
|
|
@@ -206,14 +212,28 @@ Controller.prototype.html = function(value) {
|
|
|
206
212
|
|
|
207
213
|
ctrl.response.headers['content-type'] = 'text/html';
|
|
208
214
|
|
|
209
|
-
if (value != null)
|
|
215
|
+
if (value != null)
|
|
210
216
|
ctrl.response.value = ctrl.response.minify && F.config.$minifyhtml ? F.TMinificators.html(value) : value;
|
|
211
|
-
}
|
|
212
217
|
|
|
213
218
|
ctrl.flush();
|
|
214
219
|
F.stats.response.html++;
|
|
215
220
|
};
|
|
216
221
|
|
|
222
|
+
Controller.prototype.xml = function(value) {
|
|
223
|
+
var ctrl = this;
|
|
224
|
+
|
|
225
|
+
if (ctrl.destroyed)
|
|
226
|
+
return;
|
|
227
|
+
|
|
228
|
+
if (value != null)
|
|
229
|
+
ctrl.response.value = value;
|
|
230
|
+
|
|
231
|
+
ctrl.response.headers['content-type'] = 'text/xml';
|
|
232
|
+
ctrl.flush();
|
|
233
|
+
|
|
234
|
+
F.stats.response.xml++;
|
|
235
|
+
};
|
|
236
|
+
|
|
217
237
|
Controller.prototype.text = Controller.prototype.plain = function(value) {
|
|
218
238
|
var ctrl = this;
|
|
219
239
|
|
|
@@ -229,6 +249,28 @@ Controller.prototype.text = Controller.prototype.plain = function(value) {
|
|
|
229
249
|
F.stats.response.text++;
|
|
230
250
|
};
|
|
231
251
|
|
|
252
|
+
Controller.prototype.respond = function(value, a, b) {
|
|
253
|
+
var ctrl = this;
|
|
254
|
+
var output = ctrl.response.output;
|
|
255
|
+
switch (output) {
|
|
256
|
+
case 'html':
|
|
257
|
+
case 'plain':
|
|
258
|
+
case 'text':
|
|
259
|
+
case 'xml':
|
|
260
|
+
case 'json':
|
|
261
|
+
case 'redirect':
|
|
262
|
+
case 'jsonstring':
|
|
263
|
+
case 'empty':
|
|
264
|
+
case 'file':
|
|
265
|
+
ctrl[output](value, a, b);
|
|
266
|
+
break;
|
|
267
|
+
default:
|
|
268
|
+
ctrl.json(value, a, b);
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
return ctrl;
|
|
272
|
+
};
|
|
273
|
+
|
|
232
274
|
Controller.prototype.json = function(value, beautify, replacer) {
|
|
233
275
|
var ctrl = this;
|
|
234
276
|
|
|
@@ -237,7 +279,7 @@ Controller.prototype.json = function(value, beautify, replacer) {
|
|
|
237
279
|
|
|
238
280
|
var response = ctrl.response;
|
|
239
281
|
response.headers['content-type'] = 'application/json';
|
|
240
|
-
response.headers['cache-control'] =
|
|
282
|
+
response.headers['cache-control'] = NOCACHE;
|
|
241
283
|
response.headers.vary = 'Accept-Encoding, Last-Modified, User-Agent';
|
|
242
284
|
response.headers.expires = '-1';
|
|
243
285
|
response.value = JSON.stringify(value, beautify ? '\t' : null, replacer);
|
|
@@ -253,7 +295,7 @@ Controller.prototype.jsonstring = function(value) {
|
|
|
253
295
|
|
|
254
296
|
var response = ctrl.response;
|
|
255
297
|
response.headers['content-type'] = 'application/json';
|
|
256
|
-
response.headers['cache-control'] =
|
|
298
|
+
response.headers['cache-control'] = NOCACHE;
|
|
257
299
|
response.headers.vary = 'Accept-Encoding, Last-Modified, User-Agent';
|
|
258
300
|
response.headers.expires = '-1';
|
|
259
301
|
response.value = value;
|
|
@@ -291,7 +333,7 @@ Controller.prototype.invalid = function(value) {
|
|
|
291
333
|
}
|
|
292
334
|
|
|
293
335
|
response.headers['content-type'] = 'application/json';
|
|
294
|
-
response.headers['cache-control'] =
|
|
336
|
+
response.headers['cache-control'] = NOCACHE;
|
|
295
337
|
response.headers.vary = 'Accept-Encoding, Last-Modified, User-Agent';
|
|
296
338
|
response.value = JSON.stringify(err.output(ctrl.language));
|
|
297
339
|
response.status = err.status === 408 ? 503 : err.status;
|
|
@@ -332,8 +374,8 @@ Controller.prototype.flush = function() {
|
|
|
332
374
|
response.headers['content-encoding'] = 'gzip';
|
|
333
375
|
ctrl.res.writeHead(response.status, response.headers);
|
|
334
376
|
ctrl.res.end(buffer, 'utf8');
|
|
335
|
-
ctrl.free();
|
|
336
377
|
F.stats.performance.upload += buffer.length / 1024 / 1024;
|
|
378
|
+
ctrl.free();
|
|
337
379
|
}
|
|
338
380
|
});
|
|
339
381
|
return;
|
|
@@ -343,9 +385,12 @@ Controller.prototype.flush = function() {
|
|
|
343
385
|
if (CHECK_CHARSET[type])
|
|
344
386
|
response.headers['content-type'] += '; charset=utf-8';
|
|
345
387
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
388
|
+
try {
|
|
389
|
+
ctrl.res.writeHead(response.status, response.headers);
|
|
390
|
+
ctrl.res.end(buffer);
|
|
391
|
+
} finally {
|
|
392
|
+
ctrl.free();
|
|
393
|
+
}
|
|
349
394
|
};
|
|
350
395
|
|
|
351
396
|
Controller.prototype.fallback = function(code, err) {
|
|
@@ -376,7 +421,7 @@ Controller.prototype.fallback = function(code, err) {
|
|
|
376
421
|
ctrl.response.status = 503;
|
|
377
422
|
if (!view) {
|
|
378
423
|
F.temporary.views.$pause = view = new F.TViewEngine.View();
|
|
379
|
-
view.compiled = F.TViewEngine.compile('$pause', F.Fs.readFileSync(F.Path.join(F.config.$
|
|
424
|
+
view.compiled = F.TViewEngine.compile('$pause', F.Fs.readFileSync(F.Path.join(F.config.$total5, 'pause.html'), 'utf8'), false);
|
|
380
425
|
}
|
|
381
426
|
view.model = F.paused;
|
|
382
427
|
} else {
|
|
@@ -384,7 +429,7 @@ Controller.prototype.fallback = function(code, err) {
|
|
|
384
429
|
view = F.temporary.views.$error;
|
|
385
430
|
if (!view) {
|
|
386
431
|
F.temporary.views.$error = view = new F.TViewEngine.View();
|
|
387
|
-
view.compiled = F.TViewEngine.compile('$error', F.Fs.readFileSync(F.Path.join(F.config.$
|
|
432
|
+
view.compiled = F.TViewEngine.compile('$error', F.Fs.readFileSync(F.Path.join(F.config.$total5, 'error.html'), 'utf8'), false);
|
|
388
433
|
}
|
|
389
434
|
view.model = { code: code, status: F.TUtils.httpstatus(code), error: err ? (DEBUG ? err.toString() : '') : '' };
|
|
390
435
|
}
|
|
@@ -393,6 +438,11 @@ Controller.prototype.fallback = function(code, err) {
|
|
|
393
438
|
}
|
|
394
439
|
};
|
|
395
440
|
|
|
441
|
+
Controller.prototype.layout = function(name) {
|
|
442
|
+
var ctrl = this;
|
|
443
|
+
ctrl.response.layout = name;
|
|
444
|
+
};
|
|
445
|
+
|
|
396
446
|
Controller.prototype.view = function(name, model) {
|
|
397
447
|
|
|
398
448
|
var ctrl = this;
|
|
@@ -401,10 +451,15 @@ Controller.prototype.view = function(name, model) {
|
|
|
401
451
|
return;
|
|
402
452
|
|
|
403
453
|
var view = new F.TViewEngine.View(ctrl);
|
|
404
|
-
|
|
405
|
-
|
|
454
|
+
ctrl.response.layout && view.layout(ctrl.response.layout);
|
|
455
|
+
setImmediate(renderview, view, name, model);
|
|
456
|
+
return view;
|
|
406
457
|
};
|
|
407
458
|
|
|
459
|
+
function renderview(view, name, model) {
|
|
460
|
+
view.controller.html(view.render(name, model));
|
|
461
|
+
}
|
|
462
|
+
|
|
408
463
|
Controller.prototype.file = function(path, download) {
|
|
409
464
|
|
|
410
465
|
var ctrl = this;
|
|
@@ -423,14 +478,23 @@ Controller.prototype.file = function(path, download) {
|
|
|
423
478
|
var ext = F.TUtils.getExtension(path);
|
|
424
479
|
|
|
425
480
|
if (ext === 'js') {
|
|
426
|
-
if (response.minify)
|
|
481
|
+
if (response.minify) {
|
|
427
482
|
response.minify = F.config.$minifyjs;
|
|
483
|
+
if (response.minify)
|
|
484
|
+
response.minify = !CHECK_MIN.test(path);
|
|
485
|
+
}
|
|
428
486
|
} else if (ext === 'css') {
|
|
429
|
-
if (response.minify)
|
|
487
|
+
if (response.minify) {
|
|
430
488
|
response.minify = F.config.$minifycss;
|
|
489
|
+
if (response.minify)
|
|
490
|
+
response.minify = !CHECK_MIN.test(path);
|
|
491
|
+
}
|
|
431
492
|
} else if (ext === 'html') {
|
|
432
|
-
if (response.minify)
|
|
493
|
+
if (response.minify) {
|
|
433
494
|
response.minify = F.config.$minifyhtml;
|
|
495
|
+
if (response.minify)
|
|
496
|
+
response.minify = !CHECK_MIN.test(path);
|
|
497
|
+
}
|
|
434
498
|
}
|
|
435
499
|
|
|
436
500
|
if (response.minify) {
|
|
@@ -477,7 +541,7 @@ Controller.prototype.stream = function(type, stream, download) {
|
|
|
477
541
|
if (CHECK_CHARSET[type])
|
|
478
542
|
type += '; charset=utf-8';
|
|
479
543
|
|
|
480
|
-
response.headers['content-type'] = type;
|
|
544
|
+
response.headers['content-type'] = type || 'application/octet-stream';
|
|
481
545
|
|
|
482
546
|
if (compress)
|
|
483
547
|
response.headers['content-encoding'] = 'gzip';
|
|
@@ -595,6 +659,30 @@ Controller.prototype.proxy = function(opt) {
|
|
|
595
659
|
|
|
596
660
|
};
|
|
597
661
|
|
|
662
|
+
Controller.prototype.successful = function(callback) {
|
|
663
|
+
var ctrl = this;
|
|
664
|
+
return function(err, a, b, c) {
|
|
665
|
+
if (err)
|
|
666
|
+
ctrl.invalid(err);
|
|
667
|
+
else
|
|
668
|
+
callback.call(ctrl, a, b, c);
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
Controller.prototype.done = function(arg) {
|
|
673
|
+
var ctrl = this;
|
|
674
|
+
return function(err, response) {
|
|
675
|
+
if (err)
|
|
676
|
+
ctrl.invalid(err);
|
|
677
|
+
else
|
|
678
|
+
ctrl.json(DEF.onSuccess(arg === true ? response : arg));
|
|
679
|
+
};
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
Controller.prototype.transform = function(name, value, callback) {
|
|
683
|
+
return F.transform(name, value, callback, this);
|
|
684
|
+
};
|
|
685
|
+
|
|
598
686
|
Controller.prototype.success = function(value) {
|
|
599
687
|
F.TUtils.success.value = value;
|
|
600
688
|
this.json(F.TUtils.success);
|
|
@@ -735,13 +823,22 @@ Controller.prototype.resume = function() {
|
|
|
735
823
|
|
|
736
824
|
switch (ctrl.ext) {
|
|
737
825
|
case 'js':
|
|
738
|
-
|
|
826
|
+
if (CHECK_MIN.test(path))
|
|
827
|
+
send_file(ctrl, path, ctrl.ext);
|
|
828
|
+
else
|
|
829
|
+
send_js(ctrl, path);
|
|
739
830
|
break;
|
|
740
831
|
case 'css':
|
|
741
|
-
|
|
832
|
+
if (CHECK_MIN.test(path))
|
|
833
|
+
send_file(ctrl, path, ctrl.ext);
|
|
834
|
+
else
|
|
835
|
+
send_css(ctrl, path);
|
|
742
836
|
break;
|
|
743
837
|
case 'html':
|
|
744
|
-
|
|
838
|
+
if (CHECK_MIN.test(path))
|
|
839
|
+
send_file(ctrl, path, ctrl.ext);
|
|
840
|
+
else
|
|
841
|
+
send_html(ctrl, path);
|
|
745
842
|
break;
|
|
746
843
|
default:
|
|
747
844
|
send_file(ctrl, path, ctrl.ext);
|
|
@@ -764,14 +861,15 @@ Controller.prototype.free = function() {
|
|
|
764
861
|
ctrl.payload = null;
|
|
765
862
|
|
|
766
863
|
// Potential problem
|
|
767
|
-
ctrl.body = null;
|
|
768
|
-
ctrl.params = null;
|
|
769
|
-
ctrl.query = null;
|
|
864
|
+
// ctrl.body = null;
|
|
865
|
+
// ctrl.params = null;
|
|
866
|
+
// ctrl.query = null;
|
|
770
867
|
|
|
771
868
|
if (ctrl.preventclearfiles != true)
|
|
772
869
|
ctrl.clear();
|
|
773
870
|
|
|
774
871
|
// Clear resources
|
|
872
|
+
ctrl.req.controller = null;
|
|
775
873
|
|
|
776
874
|
};
|
|
777
875
|
|
|
@@ -824,7 +922,7 @@ Controller.prototype.$route = function() {
|
|
|
824
922
|
|
|
825
923
|
ctrl.req.on('data', function(chunk) {
|
|
826
924
|
ctrl.payloadsize += chunk.length;
|
|
827
|
-
if (
|
|
925
|
+
if (ctrl.payloadsize > ctrl.route.size) {
|
|
828
926
|
if (!ctrl.toolarge) {
|
|
829
927
|
ctrl.toolarge = true;
|
|
830
928
|
delete ctrl.payload;
|
|
@@ -889,16 +987,33 @@ function readfile(filename, callback) {
|
|
|
889
987
|
});
|
|
890
988
|
}
|
|
891
989
|
|
|
892
|
-
function
|
|
990
|
+
Controller.prototype.notmodified = function(date) {
|
|
991
|
+
var ctrl = this;
|
|
893
992
|
if (ctrl.headers['if-modified-since'] === date) {
|
|
894
993
|
ctrl.response.status = 304;
|
|
895
|
-
ctrl.response.headers['cache-control'] = 'public, max-age=
|
|
994
|
+
ctrl.response.headers['cache-control'] = 'public, must-revalidate, max-age=' + F.config.$httpmaxage; // 5 min.
|
|
896
995
|
ctrl.response.headers['last-modified'] = date;
|
|
897
996
|
ctrl.flush();
|
|
898
997
|
F.stats.response.notmodified++;
|
|
899
998
|
return true;
|
|
900
999
|
}
|
|
901
|
-
}
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
Controller.prototype.httpcache = function(date) {
|
|
1003
|
+
var ctrl = this;
|
|
1004
|
+
|
|
1005
|
+
if (date instanceof Date)
|
|
1006
|
+
date = date.toUTCString();
|
|
1007
|
+
|
|
1008
|
+
if (!ctrl.response.headers.expires)
|
|
1009
|
+
ctrl.response.headers.expires = F.config.$httpexpire;
|
|
1010
|
+
|
|
1011
|
+
if (!ctrl.response.headers['cache-control'])
|
|
1012
|
+
ctrl.response.headers['cache-control'] = 'public, must-revalidate, max-age=' + F.config.$httpmaxage; // 5 minute cache for revalidate (304)
|
|
1013
|
+
|
|
1014
|
+
ctrl.response.headers['last-modified'] = date;
|
|
1015
|
+
ctrl.response.headers.etag = '858' + F.config.$httpetag;
|
|
1016
|
+
};
|
|
902
1017
|
|
|
903
1018
|
function multipart(ctrl) {
|
|
904
1019
|
|
|
@@ -938,6 +1053,7 @@ function multipart(ctrl) {
|
|
|
938
1053
|
if (index !== -1)
|
|
939
1054
|
file.filename = file.filename.substring(index + 1);
|
|
940
1055
|
|
|
1056
|
+
file.ext = F.TUtils.getExtension(file.filename);
|
|
941
1057
|
ctrl.files.push(file);
|
|
942
1058
|
}
|
|
943
1059
|
|
|
@@ -961,7 +1077,7 @@ function multipart(ctrl) {
|
|
|
961
1077
|
});
|
|
962
1078
|
|
|
963
1079
|
parser.skipcheck = !F.config.$httpchecktypes;
|
|
964
|
-
parser.limits.total = ctrl.route.size
|
|
1080
|
+
parser.limits.total = ctrl.route.size;
|
|
965
1081
|
}
|
|
966
1082
|
|
|
967
1083
|
function authorize(ctrl) {
|
|
@@ -988,21 +1104,25 @@ function authorize(ctrl) {
|
|
|
988
1104
|
execute(ctrl);
|
|
989
1105
|
}
|
|
990
1106
|
|
|
991
|
-
function execute(ctrl) {
|
|
1107
|
+
function execute(ctrl, skipmiddleware) {
|
|
992
1108
|
|
|
993
|
-
|
|
1109
|
+
if (ctrl.route.timeout)
|
|
1110
|
+
ctrl.timeout = ctrl.route.timeout;
|
|
994
1111
|
|
|
995
1112
|
for (let param of ctrl.route.params) {
|
|
996
1113
|
let value = ctrl.split[param.index];
|
|
997
1114
|
ctrl.params[param.name] = value;
|
|
998
1115
|
}
|
|
999
1116
|
|
|
1000
|
-
if (!ctrl.language && F.def.onLocalize)
|
|
1117
|
+
if (!ctrl.language && F.def.onLocalize) {
|
|
1001
1118
|
ctrl.language = F.def.onLocalize(ctrl);
|
|
1119
|
+
ctrl.uri.cache += ctrl.language;
|
|
1120
|
+
}
|
|
1002
1121
|
|
|
1003
|
-
if (ctrl.route.middleware.length) {
|
|
1122
|
+
if (!skipmiddleware && ctrl.route.middleware.length) {
|
|
1004
1123
|
middleware(ctrl);
|
|
1005
1124
|
} else {
|
|
1125
|
+
|
|
1006
1126
|
if (ctrl.route.api) {
|
|
1007
1127
|
let body = ctrl.body;
|
|
1008
1128
|
if (body && typeof(body) === 'object' && body.schema && typeof(body.schema) === 'string') {
|
|
@@ -1026,17 +1146,40 @@ function execute(ctrl) {
|
|
|
1026
1146
|
|
|
1027
1147
|
let params = {};
|
|
1028
1148
|
if (endpoint.params) {
|
|
1029
|
-
|
|
1149
|
+
let err = null;
|
|
1150
|
+
for (let m of endpoint.params) {
|
|
1030
1151
|
params[m.name] = schema[m.index] || '';
|
|
1152
|
+
if (!params[m.name]) {
|
|
1153
|
+
if (!err)
|
|
1154
|
+
err = new F.TBuilders.ErrorBuilder();
|
|
1155
|
+
err.push2('params.' + m.name);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
if (err) {
|
|
1159
|
+
ctrl.invalid(err);
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1031
1162
|
}
|
|
1163
|
+
|
|
1032
1164
|
body = body.data;
|
|
1165
|
+
|
|
1033
1166
|
if (!body || typeof(body) === 'object') {
|
|
1167
|
+
|
|
1168
|
+
if (endpoint.timeout)
|
|
1169
|
+
ctrl.timeout = endpoint.timeout;
|
|
1170
|
+
|
|
1034
1171
|
ctrl.params = params;
|
|
1035
1172
|
ctrl.query = query ? query.parseEncoded() : {};
|
|
1036
|
-
|
|
1173
|
+
let action = endpoint.action;
|
|
1174
|
+
if (action) {
|
|
1175
|
+
ctrl.body = body || {};
|
|
1176
|
+
action(ctrl);
|
|
1177
|
+
} else
|
|
1178
|
+
F.action(endpoint.actions, body || {}, ctrl).autorespond();
|
|
1037
1179
|
return;
|
|
1038
1180
|
}
|
|
1039
1181
|
}
|
|
1182
|
+
|
|
1040
1183
|
ctrl.fallback(400, 'Invalid data');
|
|
1041
1184
|
}
|
|
1042
1185
|
} else {
|
|
@@ -1062,12 +1205,17 @@ function auto_view(ctrl) {
|
|
|
1062
1205
|
|
|
1063
1206
|
function send_html(ctrl, path) {
|
|
1064
1207
|
|
|
1065
|
-
if (F.
|
|
1208
|
+
if (!ctrl.language && F.def.onLocalize) {
|
|
1209
|
+
ctrl.language = F.def.onLocalize(ctrl);
|
|
1210
|
+
ctrl.uri.cache += ctrl.language;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
if (F.temporary.notfound[ctrl.uri.cache]) {
|
|
1066
1214
|
ctrl.fallback(404);
|
|
1067
1215
|
return;
|
|
1068
1216
|
}
|
|
1069
1217
|
|
|
1070
|
-
let filename = F.temporary.minified[ctrl.uri.
|
|
1218
|
+
let filename = F.temporary.minified[ctrl.uri.cache];
|
|
1071
1219
|
if (filename) {
|
|
1072
1220
|
send_file(ctrl, filename, 'html');
|
|
1073
1221
|
return;
|
|
@@ -1076,32 +1224,33 @@ function send_html(ctrl, path) {
|
|
|
1076
1224
|
readfile(path, function(err, output) {
|
|
1077
1225
|
|
|
1078
1226
|
if (err) {
|
|
1079
|
-
|
|
1227
|
+
|
|
1228
|
+
if (!DEBUG)
|
|
1229
|
+
F.temporary.notfound[ctrl.uri.cache] = 1;
|
|
1230
|
+
|
|
1080
1231
|
ctrl.fallback(404);
|
|
1081
1232
|
return;
|
|
1082
1233
|
}
|
|
1083
1234
|
|
|
1084
|
-
if (!ctrl.language && F.def.onLocalize)
|
|
1085
|
-
ctrl.language = F.def.onLocalize(ctrl);
|
|
1086
|
-
|
|
1087
1235
|
output.body = F.translate(ctrl.language, output.body);
|
|
1088
1236
|
|
|
1089
1237
|
if (ctrl.response.minify && F.config.$minifyhtml)
|
|
1090
1238
|
output.body = F.TMinificators.html(output.body);
|
|
1091
1239
|
|
|
1092
1240
|
if (DEBUG) {
|
|
1241
|
+
ctrl.response.headers['cache-control'] = NOCACHE;
|
|
1093
1242
|
ctrl.response.headers['last-modified'] = output.date;
|
|
1094
1243
|
ctrl.response.headers['content-type'] = 'text/html';
|
|
1095
1244
|
ctrl.response.value = output.body;
|
|
1096
1245
|
ctrl.flush();
|
|
1097
1246
|
} else {
|
|
1098
|
-
let filename = F.path.tmp(F.clusterid +
|
|
1247
|
+
let filename = F.path.tmp(F.clusterid + ctrl.uri.cache.substring(1).replace(REG_FILETMP, '-') + '-min.html');
|
|
1099
1248
|
F.Fs.writeFile(filename, output.body, function(err) {
|
|
1100
1249
|
if (err) {
|
|
1101
|
-
F.temporary.notfound[ctrl.uri.
|
|
1250
|
+
F.temporary.notfound[ctrl.uri.cache] = 1;
|
|
1102
1251
|
ctrl.fallback(404, err.toString());
|
|
1103
1252
|
} else {
|
|
1104
|
-
F.temporary.minified[ctrl.uri.
|
|
1253
|
+
F.temporary.minified[ctrl.uri.cache] = filename;
|
|
1105
1254
|
send_file(ctrl, filename, 'html');
|
|
1106
1255
|
}
|
|
1107
1256
|
});
|
|
@@ -1111,12 +1260,12 @@ function send_html(ctrl, path) {
|
|
|
1111
1260
|
|
|
1112
1261
|
function send_css(ctrl, path) {
|
|
1113
1262
|
|
|
1114
|
-
if (F.temporary.notfound[ctrl.uri.
|
|
1263
|
+
if (F.temporary.notfound[ctrl.uri.cache]) {
|
|
1115
1264
|
ctrl.fallback(404);
|
|
1116
1265
|
return;
|
|
1117
1266
|
}
|
|
1118
1267
|
|
|
1119
|
-
let filename = F.temporary.minified[ctrl.uri.
|
|
1268
|
+
let filename = F.temporary.minified[ctrl.uri.cache];
|
|
1120
1269
|
if (filename) {
|
|
1121
1270
|
send_file(ctrl, filename, 'css');
|
|
1122
1271
|
return;
|
|
@@ -1125,7 +1274,10 @@ function send_css(ctrl, path) {
|
|
|
1125
1274
|
readfile(path, function(err, output) {
|
|
1126
1275
|
|
|
1127
1276
|
if (err) {
|
|
1128
|
-
|
|
1277
|
+
|
|
1278
|
+
if (!DEBUG)
|
|
1279
|
+
F.temporary.notfound[ctrl.uri.cache] = 1;
|
|
1280
|
+
|
|
1129
1281
|
ctrl.fallback(404);
|
|
1130
1282
|
return;
|
|
1131
1283
|
}
|
|
@@ -1134,18 +1286,19 @@ function send_css(ctrl, path) {
|
|
|
1134
1286
|
output.body = F.TMinificators.css(output.body);
|
|
1135
1287
|
|
|
1136
1288
|
if (DEBUG) {
|
|
1289
|
+
ctrl.response.headers['cache-control'] = NOCACHE;
|
|
1137
1290
|
ctrl.response.headers['last-modified'] = output.date;
|
|
1138
1291
|
ctrl.response.headers['content-type'] = 'text/css';
|
|
1139
1292
|
ctrl.response.value = output.body;
|
|
1140
1293
|
ctrl.flush();
|
|
1141
1294
|
} else {
|
|
1142
|
-
let filename = F.path.tmp(F.clusterid + ctrl.uri.
|
|
1295
|
+
let filename = F.path.tmp(F.clusterid + ctrl.uri.cache.substring(1).replace(REG_FILETMP, '-') + '-min.css');
|
|
1143
1296
|
F.Fs.writeFile(filename, output.body, function(err) {
|
|
1144
1297
|
if (err) {
|
|
1145
|
-
F.temporary.notfound[ctrl.uri.
|
|
1298
|
+
F.temporary.notfound[ctrl.uri.cache] = 1;
|
|
1146
1299
|
ctrl.fallback(404, err.toString());
|
|
1147
1300
|
} else {
|
|
1148
|
-
F.temporary.minified[ctrl.uri.
|
|
1301
|
+
F.temporary.minified[ctrl.uri.cache] = filename;
|
|
1149
1302
|
send_file(ctrl, filename, 'css');
|
|
1150
1303
|
}
|
|
1151
1304
|
});
|
|
@@ -1155,12 +1308,12 @@ function send_css(ctrl, path) {
|
|
|
1155
1308
|
|
|
1156
1309
|
function send_js(ctrl, path) {
|
|
1157
1310
|
|
|
1158
|
-
if (F.temporary.notfound[ctrl.uri.
|
|
1311
|
+
if (F.temporary.notfound[ctrl.uri.cache]) {
|
|
1159
1312
|
ctrl.fallback(404);
|
|
1160
1313
|
return;
|
|
1161
1314
|
}
|
|
1162
1315
|
|
|
1163
|
-
let filename = F.temporary.minified[ctrl.uri.
|
|
1316
|
+
let filename = F.temporary.minified[ctrl.uri.cache];
|
|
1164
1317
|
if (filename) {
|
|
1165
1318
|
send_file(ctrl, filename, 'js');
|
|
1166
1319
|
return;
|
|
@@ -1169,7 +1322,10 @@ function send_js(ctrl, path) {
|
|
|
1169
1322
|
readfile(path, function(err, output) {
|
|
1170
1323
|
|
|
1171
1324
|
if (err) {
|
|
1172
|
-
|
|
1325
|
+
|
|
1326
|
+
if (!DEBUG)
|
|
1327
|
+
F.temporary.notfound[ctrl.uri.cache] = 1;
|
|
1328
|
+
|
|
1173
1329
|
ctrl.fallback(404);
|
|
1174
1330
|
return;
|
|
1175
1331
|
}
|
|
@@ -1178,18 +1334,19 @@ function send_js(ctrl, path) {
|
|
|
1178
1334
|
output.body = F.TMinificators.js(output.body);
|
|
1179
1335
|
|
|
1180
1336
|
if (DEBUG) {
|
|
1337
|
+
ctrl.response.headers['cache-control'] = NOCACHE;
|
|
1181
1338
|
ctrl.response.headers['last-modified'] = output.date;
|
|
1182
1339
|
ctrl.response.headers['content-type'] = 'text/javascript';
|
|
1183
1340
|
ctrl.response.value = output.body;
|
|
1184
1341
|
ctrl.flush();
|
|
1185
1342
|
} else {
|
|
1186
|
-
let filename = F.path.tmp(F.clusterid + ctrl.uri.
|
|
1343
|
+
let filename = F.path.tmp(F.clusterid + ctrl.uri.cache.substring(1).replace(REG_FILETMP, '-') + '-min.js');
|
|
1187
1344
|
F.Fs.writeFile(filename, output.body, function(err) {
|
|
1188
1345
|
if (err) {
|
|
1189
|
-
F.temporary.notfound[ctrl.uri.
|
|
1346
|
+
F.temporary.notfound[ctrl.uri.cache] = 1;
|
|
1190
1347
|
ctrl.fallback(404, err.toString());
|
|
1191
1348
|
} else {
|
|
1192
|
-
F.temporary.minified[ctrl.uri.
|
|
1349
|
+
F.temporary.minified[ctrl.uri.cache] = filename;
|
|
1193
1350
|
send_file(ctrl, filename, 'js');
|
|
1194
1351
|
}
|
|
1195
1352
|
});
|
|
@@ -1200,15 +1357,15 @@ function send_js(ctrl, path) {
|
|
|
1200
1357
|
function send_file(ctrl, path, ext) {
|
|
1201
1358
|
|
|
1202
1359
|
// Check the file existence
|
|
1203
|
-
if (F.temporary.notfound[ctrl.uri.
|
|
1360
|
+
if (F.temporary.notfound[ctrl.uri.cache]) {
|
|
1204
1361
|
ctrl.fallback(404);
|
|
1205
1362
|
return;
|
|
1206
1363
|
}
|
|
1207
1364
|
|
|
1208
|
-
var cache = F.temporary.tmp[ctrl.uri.
|
|
1365
|
+
var cache = F.temporary.tmp[ctrl.uri.cache];
|
|
1209
1366
|
|
|
1210
1367
|
// HTTP Cache
|
|
1211
|
-
if (ctrl.response.cache && cache && notmodified(
|
|
1368
|
+
if (ctrl.response.cache && cache && ctrl.notmodified(cache.date))
|
|
1212
1369
|
return;
|
|
1213
1370
|
|
|
1214
1371
|
var accept = ctrl.headers['accept-encoding'];
|
|
@@ -1221,18 +1378,24 @@ function send_file(ctrl, path, ext) {
|
|
|
1221
1378
|
|
|
1222
1379
|
if (err) {
|
|
1223
1380
|
|
|
1224
|
-
if (ctrl.response.cache)
|
|
1225
|
-
F.temporary.notfound[ctrl.uri.
|
|
1381
|
+
if (!DEBUG && ctrl.response.cache)
|
|
1382
|
+
F.temporary.notfound[ctrl.uri.cache] = true;
|
|
1226
1383
|
|
|
1227
1384
|
ctrl.fallback(404);
|
|
1228
1385
|
return;
|
|
1229
1386
|
}
|
|
1230
1387
|
|
|
1231
|
-
if (httpcache)
|
|
1232
|
-
ctrl.response.headers.expires
|
|
1233
|
-
|
|
1388
|
+
if (httpcache) {
|
|
1389
|
+
if (!ctrl.response.headers.expires)
|
|
1390
|
+
ctrl.response.headers.expires = F.config.$httpexpire;
|
|
1391
|
+
if (!ctrl.response.headers['cache-control'])
|
|
1392
|
+
ctrl.response.headers['cache-control'] = 'public, must-revalidate, max-age=' + F.config.$httpmaxage; // 5 minute cache for revalidate (304)
|
|
1393
|
+
} else if (ctrl.response.headers.expires)
|
|
1234
1394
|
delete ctrl.response.headers.expires;
|
|
1235
1395
|
|
|
1396
|
+
if (!httpcache)
|
|
1397
|
+
ctrl.response.headers['cache-control'] = NOCACHE;
|
|
1398
|
+
|
|
1236
1399
|
if (!cache)
|
|
1237
1400
|
cache = { date: stats.mtime.toUTCString(), size: stats.size };
|
|
1238
1401
|
|
|
@@ -1245,7 +1408,7 @@ function send_file(ctrl, path, ext) {
|
|
|
1245
1408
|
type += '; charset=utf-8';
|
|
1246
1409
|
|
|
1247
1410
|
ctrl.response.headers['content-type'] = type;
|
|
1248
|
-
F.temporary.tmp[ctrl.uri.
|
|
1411
|
+
F.temporary.tmp[ctrl.uri.cache] = cache;
|
|
1249
1412
|
|
|
1250
1413
|
F.stats.performance.open++;
|
|
1251
1414
|
|
|
@@ -1303,7 +1466,7 @@ function send_file(ctrl, path, ext) {
|
|
|
1303
1466
|
|
|
1304
1467
|
function middleware(ctrl) {
|
|
1305
1468
|
var run = function(index) {
|
|
1306
|
-
|
|
1469
|
+
let name = ctrl.route.middleware[index];
|
|
1307
1470
|
if (name) {
|
|
1308
1471
|
let fn = F.routes.middleware[name];
|
|
1309
1472
|
if (fn)
|
|
@@ -1311,7 +1474,7 @@ function middleware(ctrl) {
|
|
|
1311
1474
|
else
|
|
1312
1475
|
run(index + 1);
|
|
1313
1476
|
} else
|
|
1314
|
-
|
|
1477
|
+
execute(ctrl, true);
|
|
1315
1478
|
};
|
|
1316
1479
|
run(0);
|
|
1317
1480
|
}
|
|
@@ -1372,7 +1535,7 @@ HttpFile.prototype.$move = function(filename, callback) {
|
|
|
1372
1535
|
} else {
|
|
1373
1536
|
if (!err) {
|
|
1374
1537
|
self.path = filename;
|
|
1375
|
-
self.
|
|
1538
|
+
self.removable = false;
|
|
1376
1539
|
}
|
|
1377
1540
|
callback && callback(err);
|
|
1378
1541
|
}
|