Resolving Bug 155
[osm/UI.git] / skyquake / framework / core / api_utils / utils.js
1 /*
2 *
3 * Copyright 2016 RIFT.IO Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18 // Helper Functions
19
20
21 /**
22 * Utils for use across the api_server.
23 * @module framework/core/utils
24 */
25
26 var fs = require('fs');
27 var request = require('request');
28 var Promise = require('promise');
29 var CONSTANTS = require('./constants.js');
30 var CONFD_PORT = '8008';
31 var APIVersion = '/v1';
32 var _ = require('lodash');
33
34 var requestWrapper = function(request) {
35 if (process.env.HTTP_PROXY && process.env.HTTP_PROXY != '') {
36 request = request.defaults({
37 'proxy': process.env.HTTP_PROXY
38 });
39 }
40 return request;
41 }
42
43 var confdPort = function(api_server) {
44 try {
45 api_server = api_server.replace(api_server.match(/[0-9](:[0-9]+)/)[1], '')
46 } catch (e) {
47
48 }
49 return api_server + ':' + CONFD_PORT;
50 };
51
52
53 var validateResponse = function(callerName, error, response, body, resolve, reject) {
54 var res = {};
55
56 if (error) {
57 console.log('Problem with "', callerName, '": ', error);
58 res.statusCode = 500;
59 res.errorMessage = {
60 error: 'Problem with ' + callerName + ': ' + error
61 };
62 reject(res);
63 return false;
64 } else if (response.statusCode >= 400) {
65 console.log('Problem with "', callerName, '": ', response.statusCode, ':', body);
66 res.statusCode = response.statusCode;
67
68 // auth specific
69 if (response.statusCode == 401) {
70 res.errorMessage = {
71 error: 'Authentication needed' + body
72 };
73 reject(res);
74 return false;
75 }
76
77 res.errorMessage = {
78 error: 'Problem with ' + callerName + ': ' + response.statusCode + ': ' + typeof(body) == 'string' ? body : JSON.stringify(body),
79 body: body
80 };
81
82 reject(res);
83 return false;
84 } else if (response.statusCode == 204) {
85 resolve({
86 statusCode: response.statusCode,
87 data: {}
88 });
89 return false;
90 } else {
91 return true;
92 }
93 };
94
95
96 var checkAuthorizationHeader = function(req) {
97 return new Promise(function(resolve, reject) {
98 if (req.get('Authorization') == null) {
99 reject();
100 } else {
101 resolve();
102 }
103 });
104 };
105
106 if (process.env.LOG_REQUESTS) {
107 var logFile = process.env.REQUESTS_LOG_FILE;
108
109 if (logFile && logFile != '') {
110 validateResponse = function(callerName, error, response, body, resolve, reject) {
111 var res = {};
112
113 if (error) {
114 console.log('Problem with "', callerName, '": ', error);
115 res.statusCode = 500;
116 res.errorMessage = {
117 error: 'Problem with ' + callerName + ': ' + error
118 };
119 reject(res);
120 fs.appendFileSync(logFile, 'Request API: ' + response.request.uri.href + ' ; ' + 'Error: ' + error);
121 return false;
122 } else if (response.statusCode >= 400) {
123 console.log('Problem with "', callerName, '": ', response.statusCode, ':', body);
124 res.statusCode = response.statusCode;
125
126 // auth specific
127 if (response.statusCode == 401) {
128 res.errorMessage = {
129 error: 'Authentication needed' + body
130 };
131 reject(res);
132 fs.appendFileSync(logFile, 'Request API: ' + response.request.uri.href + ' ; ' + 'Error Body: ' + body);
133 return false;
134 }
135
136 res.errorMessage = {
137 error: 'Problem with ' + callerName + ': ' + response.statusCode + ': ' + body
138 };
139
140 reject(res);
141 fs.appendFileSync(logFile, 'Request API: ' + response.request.uri.href + ' ; ' + 'Error Body: ' + body);
142 return false;
143 } else if (response.statusCode == 204) {
144 resolve();
145 fs.appendFileSync(logFile, 'Request API: ' + response.request.uri.href + ' ; ' + 'Response Body: ' + body);
146 return false;
147 } else {
148 fs.appendFileSync(logFile, 'Request API: ' + response.request.uri.href + ' ; ' + 'Response Body: ' + body);
149 return true;
150 }
151 };
152 }
153 }
154
155 /**
156 * Serve the error response back back to HTTP requester
157 * @param {Object} error - object of the format
158 * {
159 * statusCode - HTTP code to respond back with
160 * error - actual error JSON object to serve
161 * }
162 * @param {Function} res - a handle to the express response function
163 */
164 var sendErrorResponse = function(error, res) {
165 res.status(error.statusCode);
166 res.send(error);
167 }
168
169 /**
170 * Serve the success response back to HTTP requester
171 * @param {Object} response - object of the format
172 * {
173 * statusCode - HTTP code to respond back with
174 * data - actual data JSON object to serve
175 * }
176 * @param {Function} res - a handle to the express response function
177 */
178 var sendSuccessResponse = function(response, res) {
179 res.status(response.statusCode);
180 res.send(response.data);
181 }
182
183 var passThroughConstructor = function(app) {
184 app.get('/passthrough/:type/*', function(req, res) {
185 var url = req.params[0];
186 var type = req.params.type;
187 var api_server = req.query["api_server"];
188 var uri = confdPort(api_server) + APIVersion + '/' + url + '?deep';
189 // Check that type is valid
190 switch (type) {
191 case 'data':
192 ;
193 case 'collection':
194 break;
195 default:
196 res.send({});
197 }
198 new Promise(function(resolve, reject) {
199 request({
200 uri: uri,
201 method: 'GET',
202 headers: _.extend({}, CONSTANTS.HTTP_HEADERS.accept[type], {
203 'Authorization': req.get('Authorization'),
204 forever: CONSTANTS.FOREVER_ON,
205 rejectUnauthorized: false,
206 })
207 }, function(error, response, body) {
208 if (validateResponse('Passthrough: ' + url, error, response, body, resolve, reject)) {
209 resolve(JSON.parse(response.body))
210 };
211 });
212 }).then(function(data) {
213 res.send(data);
214 }, function(error) {
215 res.send({'error': error, uri: uri})
216 });;
217 });
218 }
219
220 var getPortForProtocol = function(protocol) {
221 switch (protocol) {
222 case 'http':
223 return 8000;
224 case 'https':
225 return 8443;
226 }
227 }
228
229 module.exports = {
230 /**
231 * Ensure confd port is on api_server variable.
232 **/
233 confdPort: confdPort,
234
235 validateResponse: validateResponse,
236
237 checkAuthorizationHeader: checkAuthorizationHeader,
238
239 request: requestWrapper.call(null, request),
240
241 sendErrorResponse: sendErrorResponse,
242
243 sendSuccessResponse: sendSuccessResponse,
244
245 passThroughConstructor: passThroughConstructor,
246
247 getPortForProtocol: getPortForProtocol
248 };