UNPKG

3.95 kBJavaScriptView Raw
1const os = require('os');
2const R = require('ramda');
3const requestLib = require('request');
4
5const logger = require('@src/utils/logger-utility');
6const urlUtils = require('@src/utils/url-utils');
7const stringUtils = require('@src/utils/string-utils');
8const CONSTANTS = require('@src/utils/constants');
9const pkg = require('@root/package.json');
10
11module.exports = {
12 request,
13 putByUrl
14};
15
16/**
17 * Core CLI request function with User-Agent setting.
18 *
19 * @param {object} options request options object
20 * @param {string} operation operation name for the request
21 * @param {boolean} doDebug define if debug info is needed
22 * @param {function} callback
23 */
24function request(options, operation, doDebug, callback) {
25 // Validation of input parameters
26 const requestOptions = R.clone(options);
27 if (typeof operation !== 'string' || !operation.trim()) {
28 process.nextTick(() => {
29 callback('[Fatal]: CLI request must have a non-empty operation name.');
30 });
31 return;
32 }
33 if (!urlUtils.isValidUrl(requestOptions.url)) {
34 process.nextTick(() => {
35 callback(`[Fatal]: Invalid URL:${requestOptions.url}. CLI request must call with valid url.`);
36 });
37 return;
38 }
39
40 const proxyUrl = process.env.ASK_CLI_PROXY;
41 if (stringUtils.isNonBlankString(proxyUrl)) {
42 requestOptions.proxy = proxyUrl;
43 }
44
45 // Set user-agent for each CLI request
46 if (!requestOptions.headers) {
47 requestOptions.headers = {};
48 }
49 requestOptions.headers['User-Agent'] = resolveUserAgent();
50
51 // Make request
52 requestLib(requestOptions, (error, response) => {
53 if (doDebug) {
54 logger.getInstance().debug(debugContentForResponse(operation, error, response));
55 }
56 if (error) {
57 return callback(`Failed to make request to ${operation}.\nError response: ${error}`);
58 }
59 if (!response) {
60 return callback(`Failed to make request to ${operation}.\nPlease make sure "${requestOptions.url}" is responding.`);
61 }
62 return callback(null, response);
63 });
64}
65
66/**
67 * HTTP client's upload method
68 * @param {String} url
69 * @param {Object} payload
70 * @param {String} operation
71 * @param {Boolean} doDebug
72 * @param {Function} callback
73 */
74function putByUrl(url, payload, operation, doDebug, callback) {
75 const options = {
76 url,
77 method: CONSTANTS.HTTP_REQUEST.VERB.PUT,
78 headers: {},
79 body: payload
80 };
81 request(options, operation, doDebug, (reqErr, reqResponse) => {
82 callback(reqErr, reqResponse);
83 });
84}
85
86/**
87 * Resolve User-Agent for CLI by the following the chain:
88 * (CLI Client)? - CLI Version - Node Verson - OS Type/Release
89 * CLI downstream's status is decided by the ENV_VAR "ASK_DOWNSTREAM_CLIENT"
90 */
91function resolveUserAgent() {
92 const cliUserAgentStr = `ask-cli/${pkg.version} Node/${process.version} ${os.type()}/${os.release()}`;
93 if (stringUtils.isNonBlankString(process.env.ASK_DOWNSTREAM_CLIENT)) {
94 return `${process.env.ASK_DOWNSTREAM_CLIENT} (ask-cli downstream client) ${cliUserAgentStr}`;
95 }
96 return cliUserAgentStr;
97}
98
99
100/**
101 * Form the debug info object according to the error and response from each http request
102 * @param {string} operation
103 * @param {string} error
104 * @param {object} response
105 */
106function debugContentForResponse(operation, error, response) {
107 return {
108 activity: operation,
109 error,
110 'request-id': response.headers['x-amzn-requestid'] || null,
111 request: {
112 method: response.request.method,
113 url: response.request.href,
114 headers: response.request.headers,
115 body: response.request.body
116 },
117 response: {
118 statusCode: response.statusCode,
119 statusMessage: response.statusMessage,
120 headers: response.headers
121 },
122 body: response.body
123 };
124}