-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.js
143 lines (128 loc) · 3.98 KB
/
utils.js
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
132
133
134
135
136
137
138
139
140
141
142
143
'use strict';
const https = require('https');
const http = require('http');
const HttpsProxyAgent = require('https-proxy-agent');
const url = require('url');
/**
* Makes an HTTP request to the designated endpoint with options. Passes on the HTTP response
* in an outgoing message.
* @param {Object} httpLib - http or https library, depending on which protocol to use
* @param {URL} endpoint - URL to send the request to
* @param {Object} options - options for the http(s) request
* @param {string} [body] - stringified JSON body
* @param {function} error - function to log errors
* @param {function} send - function to pass the outgoing message to.
* @param {function} done - function to call after the message has been sent
*/
const doHttpRequest = function (
httpLib,
endpoint,
options,
body,
error,
send,
done
) {
const req = httpLib.request(endpoint, options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
// Request returns error code
error(new Error(`Response status code ${res.statusCode}`));
}
let respBody = '';
res.on('data', (chunk) => {
respBody += chunk;
});
// At the end of response, pass response body as msg.payload
res.on('end', () => {
try {
const convertJSON =
res.headers['content-type'] &&
res.headers['content-type'].includes('application/json');
// if response is JSON, parse body as JSON
const payload = convertJSON ? JSON.parse(respBody) : respBody;
const msg = {
response: res,
payload,
};
send(msg);
done();
} catch (err) {
done(err);
}
});
});
req.on('error', (err) => {
done(err);
});
if (body) {
req.write(body);
}
req.end();
};
/**
* Add the Machine API endpoint path to a Tulip factory url
* @param {URL} url - the base factory url
* @returns {URL} url with added path for Machine API endpoint
*/
function getMachineAttributeEndpoint(url) {
const urlCopy = new URL(url);
urlCopy.pathname = '/api/v3/attributes/report';
return urlCopy;
}
/**
* @param {string} protocol - either https or http
* @returns library for sending http(s) requests
*/
const getHttpLib = function (protocol) {
const httpLibs = {
http,
https,
};
const httpLib = httpLibs[protocol];
if (!httpLib) {
throw new Error(`Expected protocol of http or https, got: ${protocol}`);
}
return httpLib;
};
/**
* Returns the agent for http(s) requests.
*
* Respects the http_proxy environment variable. If no proxy, then returns an agent for the
* specified protocol with given keep-alive options. If present, then returns an HttpProxyAgent
* for the proxy specified by http_proxy. If there is an issue with the http_proxy url,
* then defaults back to the normal agent with no proxy & logs an error.
*
* @param {Object} httpLib either http or https library
* @param {boolean} keepAlive whether to keep sockets around even when there are no
outstanding requests, so they can be used for future requests without
having to reestablish a TCP connection.
* @param {number} keepAliveMsecs initial delay (in milliseconds) for TCP keep-alive packets
*/
const getHttpAgent = function (httpLib, keepAlive, keepAliveMsecs) {
// honor any http proxy settings passed from env
const proxyUrl = process.env['http_proxy'];
if (proxyUrl) {
// TODO: Switch to hpagent, which is what the newer Node-RED HTTP nodes use.
// https-proxy-agent doesn't support keep alive settings, so ignore them.
try {
const options = url.parse(proxyUrl);
const agent = HttpsProxyAgent(options);
return agent;
} catch (err) {
console.error(
`could not create HttpsProxyAgent from env http_proxy=${proxyUrl}`
);
}
}
// No proxy, use keep alive options
return new httpLib.Agent({
keepAlive: keepAlive,
keepAliveMsecs: keepAliveMsecs,
});
};
module.exports = {
doHttpRequest,
getHttpAgent,
getHttpLib,
getMachineAttributeEndpoint,
};