-
Notifications
You must be signed in to change notification settings - Fork 91
Expand file tree
/
Copy pathrequest-shim.js
More file actions
131 lines (124 loc) · 5.19 KB
/
request-shim.js
File metadata and controls
131 lines (124 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
*
* This file is part of fiware-iotagent-lib
*
* fiware-iotagent-lib is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* fiware-iotagent-lib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with fiware-iotagent-lib.
* If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by the GNU Affero General Public License
* please contact with::daniel.moranjimenez@telefonica.com
*/
const config = require('../config');
const got = require('got');
const logger = require('logops');
const context = {
op: 'IoTAgentNGSI.Request'
};
const util = require('util');
/**
* Transform the "request" options into "got" options and add additional "got" defaults
*
* The following options are currently exposed:
* - `method` - HTTP Method
* - `searchParams` - query string params
* - `qs` - alias for query string params
* - `headers`
* - `responseType` - either `text` or `json`. `json` is the default
* - `json` - a supplied JSON object as the request body
* - `body` - any ASCII text as the request body
* - `url` - the request URL
* - `uri` - alternative alias for the request URL.
*
* @param {Object} options Original definition of the request using the request library
* @return {Object} Updated definition of the request using the got library
*
*/
function getOptions(options) {
const httpOptions = {
method: options.method,
searchParams: options.searchParams || options.qs,
headers: options.headers,
throwHttpErrors: options.throwHttpErrors || false,
retry: options.retry || 0,
responseType: options.responseType || 'json'
};
// got library is not properly documented, so it is not clear which takes precedence
// among body, json and form (see https://stackoverflow.com/q/70754880/1485926).
// Thus, we are enforcing our own precedence with the "else if" chain below.
// Behaviour is consistent with the one described at usermanual.md#iotagentlibrequest
if (options.method === 'GET' || options.method === 'HEAD' || options.method === 'OPTIONS') {
// Do nothing - Never add a body
} else if (options.body) {
// body takes precedence over json or form
httpOptions.body = options.body;
} else if (options.json) {
// json takes precedence over form
httpOptions.json = options.json;
} else if (options.form) {
// Note that we don't consider 'form' part of the function API (check usermanual.md#iotagentlibrequest)
// but we are preparing the code anyway as a safe measure
httpOptions.form = options.form;
}
return httpOptions;
}
/*
*
* Make a direct HTTP request using the underlying request library
* (currently [got](https://github.com/sindresorhus/got)),
*
* This function mimics the interface of the obsolete request library and switches
* back from promises to callbacks to avoid re-writing large chunks of code.
* This centralizes all HTTP requests in a single location and is useful
* when creating agents which use an HTTP transport for their southbound
* commands, and removes the need for the custom IoT Agent to import its own
* additonal request library.
*
* @param {Object} options Definition of the request .
* @param {Function} callback The callback function.
*
*/
let retryCount = 0; //default retry_count value
function request(options, callback) {
const retryTime = config.ORION_DEFAULT_RETRY_TIME;
const retries = config.ORION_DEFAULT_RETRIES;
const httpOptions = getOptions(options);
logger.debug(context, 'Options: %s', JSON.stringify(options, null, 4));
got(options.url || options.uri, httpOptions)
.then((response) => {
logger.debug(context, 'Response %s', JSON.stringify(response.body, null, 4));
retryCount = 0;
return callback(null, response, response.body);
})
.catch((error) => {
if (error.code === 'ECONNREFUSED') {
if (retryCount < retries) {
retryCount++;
console.log('Retrying connection', JSON.stringify(retryCount));
return setTimeout(request, retryTime * 1000 , options, callback);
}
//retrun the error
else {
retryCount = 0;
logger.debug(context, 'Error: %s', JSON.stringify(util.inspect(error), null, 4));
return callback(error);
}
}
else{
logger.debug(context, 'Error: %s', JSON.stringify(util.inspect(error), null, 4));
return callback(error);
}
});
}
module.exports = request;