UNPKG

7 kBJavaScriptView Raw
1/*
2
3 This file is a part of node-on-train project.
4
5 Copyright (C) Thanh D. Dang <thanhdd.it@gmail.com>
6
7 node-on-train is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 node-on-train is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 */
21
22
23 var fs = require('fs');
24 var trainjs = require('../lib/train.js');
25 var http = require('http');
26 var url = require('url');
27 var exec = require('child_process').exec;
28 var Fiber = require('fibers');
29 var path = require('path');
30
31
32 var global_v_init = trainjs.initServer();
33
34 var pre_run_path = ROOT_APP + '/config/pre_run.js';
35 var pre_run = fs.existsSync( pre_run_path );
36
37 var app_config = require( ROOT_APP + '/config/application.js' );
38 var ApplicationController = require( ROOT_APP + '/app/controllers/application_controller.js' );
39
40
41 var app = require( ROOT_APP + '/app.js' );
42
43 var beforeAction = function(req, res, next, class_object, action, before_action_i) {
44 if (class_object['before_action']) {
45 var before_action = class_object['before_action'][before_action_i];
46 if (!before_action.only || before_action.only && before_action.only.indexOf(action) > -1) {
47 if (class_object[before_action.action](req, res, next)) { //if res.end()
48 return;
49 }
50
51 if (before_action_i < class_object['before_action'].length - 1) {
52 before_action_i = before_action_i + 1;
53 beforeAction(req, res, next, class_object, action, before_action_i);
54 } else {
55 class_object[action](req, res, next);
56 }
57 } else {
58 class_object[action](req, res, next);
59 }
60 } else {
61 class_object[action](req, res, next);
62 }
63};
64
65function runServer() {
66 app.use(function (req, res, next) {
67 Fiber(function() {
68 var url_parts = url.parse(req.url, true);
69 req.query = url_parts.query;
70
71 if ( app_config.cors ) {
72 res.setHeader("Access-Control-Allow-Origin", "*");
73 res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
74 if (req.headers['access-control-request-headers'])
75 res.setHeader("Access-Control-Allow-Headers", req.headers['access-control-request-headers']);
76 }
77
78 if ( req.method === 'OPTIONS' ) {
79 res.end();
80 } else {
81 res.setHeader("Content-Type", "application/json");
82 next();
83 }
84 }).run();
85 });
86
87 var application = new ApplicationController();
88 app.use(application.before);
89 trainjs.newServer(app, global_v_init);
90
91 app.use(function (req, res, next) {
92 var assets = ['image/', 'text/html', 'application/javascript', 'text/css', 'application/font'];
93 var content_type = 'text/plain';
94
95 if (req.headers.accept) {
96 var headers_accept = req.headers.accept.split(',');
97 content_type = headers_accept[0];
98
99 for (var i in headers_accept) {
100 if ( headers_accept[i].indexOf('text/plain') > -1 ) {
101 content_type = 'text/html';
102 }
103 }
104
105 if (req.headers['content-type'])
106 content_type = req.headers['content-type'];
107
108 if (content_type == '*/*' && /\.js$/.test(req.url)) {
109 content_type = 'application/javascript';
110 }
111
112 if (/\.png$/.test(req.url)) {
113 content_type = 'image/png';
114 }
115
116 if (content_type == '*/*' && /\.jpg$/.test(req.url)) {
117 content_type = 'image/jpeg';
118 }
119 }
120
121 var url_path = req.url.split('?')[0];
122
123 var is_asset = false;
124 for (var k in assets) {
125 if ( content_type.indexOf(assets[k]) > -1 ) {
126 is_asset = true;
127 break;
128 }
129 }
130
131 if ( url_path.indexOf('/node_modules/') > -1 && url_path.indexOf('../') < 0 ) {
132 url_path = '..' + url_path;
133 }
134
135 var file_path = path.join(ROOT_APP, '/public', url_path);
136 if (is_asset && fs.existsSync(file_path)) {
137 if (url_path == '/') {
138 fs.readFile(ROOT_APP + '/public/index.html', function(err, page) {
139 res.writeHead(200, {'Content-Type': 'text/html'});
140 res.write(page);
141 res.end();
142 });
143 } else {
144 fs.readFile(file_path, function(err, page) {
145 res.writeHead(200, {'Content-Type': content_type});
146 res.write(page);
147 res.end();
148 });
149 }
150 } else {
151 file_path = path.join(ROOT_APP, '', url_path);
152 if (fs.existsSync(file_path)) {
153 try {
154 var stats = fs.lstatSync(file_path);
155 if (stats.isDirectory()) {
156 var index_file = file_path + '/index.html';
157 if (fs.existsSync(index_file)) {
158 if (url_path[url_path.length - 1] != '/') {
159 res.writeHead(301, {'Location': url_path + '/'});
160 res.end();
161 } else {
162 fs.readFile(index_file, function(err, page) {
163 res.writeHead(200, {'Content-Type': 'text/html'});
164 res.write(page);
165 res.end();
166 });
167 }
168 } else {
169 res.end();
170 }
171 } else {
172 if (is_asset) {
173 fs.readFile(file_path, function(err, page) {
174 res.writeHead(200, {'Content-Type': content_type});
175 res.write(page);
176 res.end();
177 });
178 } else {
179 res.end();
180 }
181 }
182 }
183 catch (e) {
184 console.log(e);
185 }
186 } else {
187 var routes = global_v_init.routes;
188 var controllers = global_v_init.controllers;
189 var is_route = false;
190
191 for (var k in ROUTE_PATTERNS) {
192 var pattern = ROUTE_PATTERNS[k].pattern;
193 var method = ROUTE_PATTERNS[k].method;
194 var resource = ROUTE_PATTERNS[k].resource;
195 var action = ROUTE_PATTERNS[k].action;
196
197 if (pattern.matches(req.url) && method.toLowerCase() == req.method.toLowerCase()) {
198 var params = pattern.match(req.url);
199 req.params = params.namedParams;
200 try {
201 var class_object = new controllers[resource]();
202 beforeAction(req, res, next, class_object, action, 0);
203 is_route = true;
204 break;
205 } catch(e) {
206 console.log( 'Error: '.bold.red + e );
207 res.end();
208 }
209 }
210 }
211
212 if (!is_route)
213 next();
214 }
215 }
216 });
217
218 var port = '1337';
219 if (process.env.PORT) {
220 port = process.env.PORT;
221 } else {
222 var port_param_index = process.argv.indexOf("-p");
223 var isNormalInteger = function (str) {
224 var n = ~~Number(str);
225 return String(n) === str && n >= 0;
226 };
227 if ( port_param_index > -1 && process.argv[ port_param_index + 1 ] && isNormalInteger( process.argv[ port_param_index + 1 ] ) ) {
228 port = process.argv[ port_param_index + 1 ];
229 }
230 }
231
232 http.createServer(app).listen(port);
233 console.log('=> Server running at http://0.0.0.0:' + port + '\n=> Ctrl-C to shutdown server');
234}
235
236if ( pre_run ) {
237 var cmd = require( pre_run_path );
238 console.log('=> Run config/pre_run.js');
239 exec(cmd, function (error, stdout, stderr) {
240 if (error) console.log(error);
241 else {
242 PRE_RUN_STDOUT = stdout;
243 runServer();
244 }
245 });
246} else {
247 runServer();
248}