UNPKG

6.64 kBJavaScriptView Raw
1var url = require('url');
2var clc = require('cli-color');
3
4var clcError = clc.red;
5var clcWarn = clc.yellow;
6var apiDirectory = undefined;
7var os = require('os');
8
9exports.sockets = function SocketController(app, io, sessionStore, mongoose, apiLocation) {
10 apiDirectory = apiLocation;
11
12 io.sockets.on('connection', function(socket) {
13 apiSocket(socket, sessionStore);
14 });
15
16 app.all(/^\/api/, function(req, res) {
17 httpCall(req, res);
18 });
19};
20
21function addSocketsToRoom(session, socket) {
22 socket.join('onlineUsers');
23 if (!session || !socket || !serverConfig.api.addSocketsToRoom) {
24 return;
25 }
26 serverConfig.api.addSocketsToRoom(session, socket);
27}
28
29function apiSocket(socket, sessionStore) {
30
31 socket.on('disconnect', function() {
32 if (io.clients) {
33 io.clients.removeSocket(socket.id);
34 }
35 });
36
37 socket.on('api', function(fileName, method, data, fn) {
38 var extras = {
39 mongoose: mongoose,
40 io: io,
41 socket: socket,
42 connectionType: 'socket',
43 hostname: os.hostname()
44 };
45 extras = getIPAddress(extras);
46 extras.fileName = fileName;
47 // this is for iOS
48 if (fileName && fileName.path) {
49 fileName = fileName.path;
50 }
51 if (method && method.method) {
52 method = method.method;
53 }
54 var sessionID = socket.request.sessionID;
55 if (!sessionID) {
56 return;
57 }
58 var fn = arguments[arguments.length - 1];
59 if (typeof fn != 'function') {
60 fn = function() {};
61 }
62 sessionStore.load(sessionID, function(storeErr, session) {
63 if (storeErr) {
64 return fn('error getting a session');
65 }
66 addSocketsToRoom(session, socket);
67 socket.join(sessionID);
68
69 // update redis online users
70 if (session) {
71 session.sessionID = sessionID;
72 session.save();
73 }
74
75 if (typeof fileName == 'object') {
76 // allows for several asynchronous calls. Super sweet! Sends data to client as received
77 var apiVersion = '';
78 if (!serverConfig.preventApiVersioning) {
79 var apiVersion = typeof method == 'string' ? method : 'v1/';
80 }
81 var array = fileName;
82 var count = 0;
83 var last = array.length;
84 var sendArray = [];
85 for (var i in array) {
86 getApi(array, i);
87 }
88
89 function getApi(array, i) {
90 try {
91 var file = array[i].location;
92 var method = array[i].method;
93 var data = array[i].data;
94 API[apiVersion + file][method](data, function(err, data) {
95 var dataToSend = data;
96 if (err) {
97 dataToSend = {
98 err: err
99 };
100 }
101 sendToClient(dataToSend, i);
102 }, session, extras);
103 } catch (err) {
104 if (err && err.stack && err.stack.indexOf && err.stack.indexOf('Error: Cannot find module') != -1) {
105 console.log(clcWarn('cannot find API::', array[i].location, array[i].method, array[i].data));
106 console.log(clcError(err));
107 return sendToClient({
108 err: "Cannot find API '" + array[i].method + "' in '" + array[i].location + ".js.'"
109 }, i);
110 }
111 console.log('Error with API call::');
112 console.log(err.stack);
113 sendToClient({
114 err: fileName
115 }, i);
116 }
117 }
118
119 function sendToClient(data, i) {
120 count++;
121 sendArray[i] = data;
122 if (count === last) {
123 fn(sendArray, null);
124 }
125 }
126 } else {
127 try {
128 API[fileName][method](data, function(err, data) {
129 // we send it this way because iOS can't recieve multiple arguments
130 if (err) {
131 if (!data) {
132 data = {}
133 }
134 data.err = err;
135 }
136 if (typeof data == 'object') {
137 data = JSON.parse(JSON.stringify(data));
138 }
139 fn(data, err);
140 }, session, extras);
141 } catch (err) {
142 if (err && err.stack && err.stack.indexOf && err.stack.indexOf('Error: Cannot find module' != -1)) {
143 console.log(clcWarn('cannot find API::', fileName, method, data));
144 console.log(clcError(err));
145 return fn(null, {
146 err: "Cannot find API '" + method + "' in '" + fileName + ".js.'"
147 });
148 }
149 console.log('Error with API call::');
150 console.log(err.stack)
151 fn(null, {
152 err: [fileName, method, data]
153 });
154 }
155 }
156 });
157 });
158}
159
160function httpCall(req, res, extras) {
161 req.session.sessionID = req.sessionID;
162 var method = req.method;
163 var extras = {
164 mongoose: mongoose,
165 io: io,
166 req: req,
167 res: res,
168 connectionType: 'http',
169 method: method,
170 hostname: os.hostname()
171 };
172 extras = getIPAddress(extras);
173 var fileName;
174 var requestData = data = (method == 'GET' || method == 'DELETE') ? req.query : req.body;
175 try {
176 var urlDic = url.parse(req.url).pathname.replace(/^\//, '');
177 urlDic = urlDic.split('/');
178 var fileName = '';
179 for (var i = 1; i < urlDic.length - 1; i++) {
180 fileName += '/' + urlDic[i];
181 }
182 fileName = fileName.slice(1, fileName.length);
183 var api = projRequire(apiDirectory + fileName + '.js');
184 var apiMethod = urlDic[urlDic.length - 1];
185 API[fileName][apiMethod](requestData, function(err, doc) {
186 if (err) {
187 res.send({
188 'err': err
189 });
190 } else {
191 res.send(doc);
192 }
193 }, req.session, extras);
194 } catch (err) {
195 if (err && err.stack && err.stack.indexOf && err.stack.indexOf('Error: Cannot find module' != -1)) {
196 console.log(clcWarn('cannot find API::', fileName, method, data));
197 console.log(clcError(err));
198 return res.status(404).send("Cannot find API '" + method + "' in '" + fileName + ".js.'");
199 }
200 console.log('Error with API call::');
201 console.log(err.stack)
202 res.status(404).send('Not a proper api call');
203 }
204}
205
206function getIPAddress(extras) {
207 var ipAddress = 'unknown';
208 if (extras.socket) {
209 ipAddress = extras.socket.request.connection.remoteAddress;
210 if (extras.socket.handshake.headers['x-forwarded-for']) {
211 ipAddress = extras.socket.handshake.headers['x-forwarded-for'];
212 }
213 } else if (extras.req) {
214 ipAddress = extras.req.connection.remoteAddress;
215 if (extras.req.headers['x-forwarded-for']) {
216 ipAddress = extras.req.headers['x-forwarded-for'];
217 }
218 }
219 extras.ipAddress = ipAddress;
220 return extras;
221}