UNPKG

10.2 kBJavaScriptView Raw
1var clc = require('cli-color');
2
3var clcError = clc.red;
4var clcWarn = clc.yellow;
5
6// configure extras and globals
7exports.extra = function(projectDir) {
8 GLOBAL.projRequire = function(module) {
9 if (module == undefined) {
10 return;
11 }
12 if (module.indexOf('/') != 0) {
13 module = '/' + module;
14 }
15 return require(projectDir + module);
16 }
17 GLOBAL.rootUrl = projectDir;
18 return exports;
19};
20
21// configure server
22exports.server = function() {
23 var envLocation, apiLocation, mongooseSchemaLocation, config;
24 var fn = arguments[1];
25 if (typeof arguments[0] == 'object') {
26 config = arguments[0];
27 envLocation = config.envLocation;
28 //remove in the future. This prevents forcing config object to have apiLocation
29 if (!config.api) {
30 config.api = {};
31 }
32 config.api.location = apiLocation = config.api.location ? config.api.location : config.apiLocation;
33 mongooseSchemaLocation = config.mongooseSchemaLocation;
34 } else {
35 throw 'You do not have the right parameters.';
36 }
37 if (!config) {
38 throw 'Must include a config file.';
39 }
40 GLOBAL.serverConfig = config;
41 config.server = config.server ? config.server : 'Main';
42 config.servers = config.servers ? config.servers : [config.server];
43
44 /* Dependencies */
45 var express = require('express');
46 var mongoose = require('mongoose');
47 var cookie = require('cookie');
48 var connect = require('connect');
49 var session = require('express-session');
50 var errorHandler = require('errorhandler');
51
52 /* Vars */
53 var app = express();
54 var http = require('http');
55 http.globalAgent.maxSockets = Infinity;
56 var server = http.createServer(app);
57 var RedisStore = require('connect-redis')(session);
58 var os = require('os');
59 var fs = require('fs');
60 var https = require('https');
61 var url = require('url');
62 var signature = require('cookie-signature');
63
64 if (typeof config.ssl == 'object') {
65 config.ssl.key = config.ssl.key != undefined ? config.ssl.key : 'ssl/key.pem';
66 config.ssl.cert = config.ssl.cert != undefined ? config.ssl.cert : 'ssl/cert.pem';
67 var credentials = {
68 key: fs.readFileSync(rootUrl + '/' + config.ssl.key),
69 cert: fs.readFileSync(rootUrl + '/' + config.ssl.cert)
70 };
71 config.serverSSL = https.createServer(credentials, app);
72 }
73
74 projRequire(envLocation).configureEnvironment(app, process);
75 if (!process.env.REDIS_URI) {
76 throw 'Must define "REDIS_URI" in the environment variables.';
77 } else if (!process.env.SESSION_KEY) {
78 throw 'Must define "SESSION_KEY" in the environment variables.';
79 } else if (!process.env.SESSION_SECRET) {
80 throw 'Must define "SESSION_SECRET" in the environment variables.';
81 } else if (!process.env.COOKIE_KEY) {
82 throw 'Must define "COOKIE_KEY" in the environment variables.';
83 } else if (!process.env.MONGO_URI) {
84 throw 'Must define "MONGO_URI" in the environment variables.';
85 }
86
87 var logger;
88 if (config.logger) {
89 var servers;
90 if (config.servers) {
91 servers = config.servers;
92 }
93 logger = require('redis-logger').init(servers, os.hostname());
94 }
95
96 var redisUrl = url.parse(process.env.REDIS_URI);
97 app.set('redisHost', redisUrl.hostname);
98 app.set('redisPort', redisUrl.port);
99
100 if (redisUrl.auth) {
101 var redisAuth = redisUrl.auth.split(':');
102 app.set('redisDb', redisAuth[0]);
103 app.set('redisPass', redisAuth[1]);
104 }
105
106 if (redisUrl.path) {
107 app.set('redisDbIndex', redisUrl.path.slice(1, redisUrl.path.length));
108 } else {
109 app.set('redisDbIndex', 0);
110 }
111
112 var cookieParser = require('cookie-parser')(process.env.COOKIE_KEY);
113 app.use(cookieParser);
114 app.use(function(req, res, next) {
115 res.header('Access-Control-Allow-Credentials', true);
116 res.header('Access-Control-Allow-Origin', req.headers.origin);
117 res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
118 res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
119 next();
120 });
121
122 var redisStoreConfig = {
123 url: process.env.REDIS_URI
124 };
125 if (!config.dontUseRedisTTL) {
126 redisStoreConfig.ttl = config.ttl || 3600;
127 }
128 var sessionStore = new RedisStore(redisStoreConfig);
129
130 /* Redis Setup */
131 app.use(session({
132 key: process.env.SESSION_KEY,
133 secret: process.env.SESSION_SECRET,
134 store: sessionStore
135 }));
136
137 if (config.sessionExpireDate != undefined) {
138 app.use(function(req, res, next) {
139 req.session.cookie.expires = config.sessionExpireDate;
140 next();
141 })
142 }
143 if (app.get('env') === 'development') {
144 app.use(errorHandler({
145 dumpExceptions: true,
146 showStack: true
147 }));
148 } else {
149 process.addListener('uncaughtException', function(err) {
150 console.error((new Date).toUTCString() + ' uncaughtException:', err.message);
151 console.error(err.stack);
152 process.exit();
153 });
154 }
155 // for file uploads
156 var bodyParser = require('body-parser');
157
158 app.use(bodyParser.urlencoded({
159 extended: true,
160 limit: '2048mb'
161 }));
162
163 app.use(bodyParser.json({
164 limit: '2048mb'
165 }));
166
167 // favicon
168 var favicon = rootUrl + '/public/img/favicon.ico'
169 if (config.favicon != undefined) {
170 favicon = rootUrl + '/' + config.favicon;
171 }
172
173 app.use(require('serve-favicon')(favicon), function() {
174 console.log(err, favicon_url)
175 });
176
177 app.use(require('method-override')());
178 app.use(errorHandler());
179 if (app.get('env') == 'production') {
180 //This is ssl, add when ready
181 app.all('*', function(req, res, next) {
182 if (req.url.indexOf('healthcheck') !== -1) {
183 res.send('server is running');
184 return;
185 }
186 if (config.sslRedirect) {
187 if (req.headers.host == undefined) {
188 res.send('');
189 } else if (req.headers.host.match(/^www/) !== null) {
190 res.redirect('https://' + req.headers.host.replace(/^www\./, '') + req.url);
191 } else if (req.protocol.indexOf('https') === -1) {
192 res.redirect('https://' + req.headers.host + req.url);
193 } else {
194 next();
195 }
196 } else {
197 next();
198 }
199 });
200 }
201
202 // assuming io is the Socket.IO server object!
203 var io = require('socket.io')(server);
204 io.use(function(socket, next) {
205 var handshakeData = socket.request;
206 if (handshakeData.headers.cookie) {
207 handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
208 try {
209 var real_sid = handshakeData.cookie[process.env.SESSION_KEY].replace('s:', '');
210 real_sid = signature.unsign(real_sid, process.env.SESSION_SECRET);
211
212 handshakeData.sessionID = real_sid;
213 } catch (err) {
214 console.log(clcError(err));
215 return next('Looks like we\'ve got a hacker on our hands.', false);
216 }
217
218 if (handshakeData.cookie[process.env.SESSION_KEY] == handshakeData.sessionID) {
219 console.log(clcError('Cookie is invalid'));
220 return next('Cookie is invalid.', false);
221 }
222
223 } else {
224 return next('No cookie transmitted.', false);
225 }
226 next(null, true);
227 });
228
229 var ioRedis = require('socket.io-redis');
230 var redisIO = require('redis');
231 var pubIO = redisIO.createClient(app.set('redisPort'), app.set('redisHost'), {
232 return_buffers: true
233 });
234 var subIO = redisIO.createClient(app.set('redisPort'), app.set('redisHost'), {
235 return_buffers: true
236 });
237
238 pubIO.auth(app.set('redisPass'), function(err) {
239 if (err) {
240 throw err;
241 }
242 });
243 subIO.auth(app.set('redisPass'), function(err) {
244 if (err) {
245 throw err;
246 }
247 });
248
249 // for redis online users
250 io.adapter(ioRedis({
251 key: 'io:' + config.appName,
252 pubClient: pubIO,
253 subClient: subIO
254 }));
255
256 if (config.onlineUsersConfig) {
257 config.onlineUsersConfig.type = 'update';
258 var client = redisIO.createClient(app.set('redisPort'), app.set('redisHost'), {});
259 client.select(app.set('redisDbIndex') || 0, function(err) {
260 if (err) {
261 throw err;
262 }
263 });
264 client.auth(app.set('redisPass'), function(err) {
265 if (err) {
266 throw err;
267 }
268 });
269 config.onlineUsersConfig.io = io;
270 config.onlineUsersConfig.dataClient = client;
271 config.onlineUsersConfig.appName = config.appName;
272 config.onlineUsersConfig.serverName = config.server + ':' + os.hostname();
273 var OnlineUsers = require('socket.io-online-users');
274 io.clients = new OnlineUsers.update(config.onlineUsersConfig);
275 }
276
277 if (!config.turnOffAwesomeLogs && logger) {
278 logger.logPage(app, config.logger.username, config.logger.password, '/redis-logger.html').socket(io);
279 }
280 mongoose.connect(process.env.MONGO_URI, function(err) {
281 if (err) {
282 return console.log(clcError('Connecting to mongoose error::', err));
283 }
284 });
285
286 mongoose.schema = projRequire(mongooseSchemaLocation);
287 require('./helpers.js').makeGlobal(config, mongoose, io).attachAPI();
288 if (config.preContent) {
289 projRequire(config.preContent).content(app, io, mongoose);
290 }
291
292 require('./controller.js').sockets(app, io, sessionStore, mongoose, apiLocation);
293
294 if (config.postContent) {
295 projRequire(config.postContent).content(app, io, mongoose);
296 }
297 if (config.useStaticServer != undefined) {
298 if (config.viewEngine) {
299 app.set('view engine', config.viewEngine);
300 } else {
301 app.set('view engine', 'jade');
302 }
303 if (config.viewDirectory) {
304 app.set('views', rootUrl + '/' + config.viewDirectory);
305 } else {
306 app.set('views', rootUrl + '/views');
307 }
308 app.locals.basedir = app.get('views');
309 if (config.publicDirectory) {
310 app.use(express.static(rootUrl + '/' + config.publicDirectory));
311 } else {
312 app.use(express.static(rootUrl + '/public'));
313 }
314 }
315
316 var port = process.env.PORT || config.port || 4050;
317 server.listen(port);
318 console.log('NM server started on port ' + port);
319 if (fn) {
320 return fn();
321 }
322
323 if (typeof config.ssl == 'object') {
324 var sslPort;
325 if (process.env.PORT) {
326 sslPort = 443;
327 } else if (config.ssl.port) {
328 sslPort = config.ssl.port
329 } else {
330 sslPort = 5051;
331 }
332 config.serverSSL.listen(sslPort);
333 console.log('NM server started on ssl port ' + sslPort);
334 if (fn) {
335 return fn();
336 }
337 }
338};