@envoy/envoy-integrations-sdk 1.4.2 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/package.yaml +1 -1
- package/lib/EnvoyAPI.js +1 -19
- package/lib/request-wrapper.js +122 -0
- package/package.json +3 -4
- package/test/promises.test.js +8 -6
package/lib/EnvoyAPI.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const request = require('request-
|
|
1
|
+
const request = require('./request-wrapper');
|
|
2
2
|
const EnvoyResponseError = require('./EnvoyResponseError');
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -362,24 +362,6 @@ class EnvoyAPI {
|
|
|
362
362
|
return EnvoyAPI.getDataFromBody(body);
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
/**
|
|
366
|
-
* Fetches a plugin install.
|
|
367
|
-
*
|
|
368
|
-
* @param {number} installId
|
|
369
|
-
* @returns {Promise<{}>}
|
|
370
|
-
*/
|
|
371
|
-
async getPluginInstall(installId) {
|
|
372
|
-
return new Promise((resolve, reject) => {
|
|
373
|
-
this.request({
|
|
374
|
-
method: 'GET',
|
|
375
|
-
url: `/api/v2/plugin-services/installs/${installId}`,
|
|
376
|
-
}).then(body => resolve(EnvoyAPI.getDataFromBody(body)))
|
|
377
|
-
.catch((error) => {
|
|
378
|
-
EnvoyAPI.safeRequestsError(error).catch((err) => reject(err));
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
365
|
/**
|
|
384
366
|
* Gets the plugin install's config.
|
|
385
367
|
*
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const cypressRequest = require('@cypress/request');
|
|
2
|
+
|
|
3
|
+
// RequestError class based on request-promise-native's
|
|
4
|
+
function RequestError(cause, options, response) {
|
|
5
|
+
this.name = 'RequestError';
|
|
6
|
+
this.message = String(cause);
|
|
7
|
+
this.cause = cause;
|
|
8
|
+
this.error = cause; // legacy attribute
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.response = response;
|
|
11
|
+
|
|
12
|
+
if (Error.captureStackTrace) {
|
|
13
|
+
Error.captureStackTrace(this);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
RequestError.prototype = Object.create(Error.prototype);
|
|
17
|
+
RequestError.prototype.constructor = RequestError;
|
|
18
|
+
|
|
19
|
+
// StatusCodeError class for non-2xx HTTP responses
|
|
20
|
+
function StatusCodeError(statusCode, body, options, response) {
|
|
21
|
+
this.name = 'StatusCodeError';
|
|
22
|
+
this.statusCode = statusCode;
|
|
23
|
+
this.message = `${statusCode} - ${JSON && JSON.stringify ? JSON.stringify(body) : body}`;
|
|
24
|
+
this.error = body; // legacy attribute
|
|
25
|
+
this.options = options;
|
|
26
|
+
this.response = response;
|
|
27
|
+
|
|
28
|
+
if (Error.captureStackTrace) {
|
|
29
|
+
Error.captureStackTrace(this);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
StatusCodeError.prototype = Object.create(Error.prototype);
|
|
33
|
+
StatusCodeError.prototype.constructor = StatusCodeError;
|
|
34
|
+
|
|
35
|
+
function normalizeRequestParams(options, callback) {
|
|
36
|
+
if (typeof options === 'string' && typeof callback === 'object') {
|
|
37
|
+
return Object.assign({ url: options }, callback);
|
|
38
|
+
}
|
|
39
|
+
if (typeof options === 'string') {
|
|
40
|
+
return { url: options };
|
|
41
|
+
}
|
|
42
|
+
return options;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createErrorWithOptions(err, options, response) {
|
|
46
|
+
return new RequestError(err, options, response);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function resolveResponse(resolve, reject, response, body, options) {
|
|
50
|
+
// Check for non-2xx status codes (request-promise-native's simple: true behavior)
|
|
51
|
+
const simple = options.simple !== false;
|
|
52
|
+
const is2xx = response && /^2/.test(String(response.statusCode));
|
|
53
|
+
|
|
54
|
+
if (simple && !is2xx && response) {
|
|
55
|
+
reject(new StatusCodeError(response.statusCode, body, options, response));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (options.resolveWithFullResponse) {
|
|
60
|
+
resolve(response);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
resolve(body);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// A wrapper that mimics request-promise-native behavior
|
|
67
|
+
function createRequestWrapper(requestFn) {
|
|
68
|
+
return function requestWrapper(options, callback) {
|
|
69
|
+
const requestOptions = normalizeRequestParams(options, callback);
|
|
70
|
+
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
requestFn(requestOptions, (err, response, body) => {
|
|
73
|
+
if (err) {
|
|
74
|
+
reject(createErrorWithOptions(err, requestOptions, response));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
resolveResponse(resolve, reject, response, body, requestOptions);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const promisifiedRequest = createRequestWrapper(cypressRequest);
|
|
84
|
+
|
|
85
|
+
// Add defaults method to maintain compatibility with request-promise-native
|
|
86
|
+
promisifiedRequest.defaults = function defaultHandler(defaultOptions) {
|
|
87
|
+
const requestWithDefaults = cypressRequest.defaults(defaultOptions);
|
|
88
|
+
|
|
89
|
+
// A wrapper that also merges the default options for error handling
|
|
90
|
+
const promisifiedWithDefaults = function promisifiedWithDefaults(options, callback) {
|
|
91
|
+
const requestOptions = normalizeRequestParams(options, callback);
|
|
92
|
+
|
|
93
|
+
// Merge default options with request options for the error.options property
|
|
94
|
+
const mergedOptions = Object.assign({}, defaultOptions, requestOptions);
|
|
95
|
+
|
|
96
|
+
// Maintain compatibility with request-promise-native:
|
|
97
|
+
const isFullUrl = requestOptions.url
|
|
98
|
+
&& (requestOptions.url.startsWith('http://') || requestOptions.url.startsWith('https://'));
|
|
99
|
+
|
|
100
|
+
if (defaultOptions.baseUrl && isFullUrl) {
|
|
101
|
+
const error = new Error('options.uri must be a path when using options.baseUrl');
|
|
102
|
+
return Promise.reject(createErrorWithOptions(error, mergedOptions));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
requestWithDefaults(requestOptions, (err, response, body) => {
|
|
107
|
+
if (err) {
|
|
108
|
+
reject(createErrorWithOptions(err, mergedOptions, response));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
resolveResponse(resolve, reject, response, body, mergedOptions);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Copy the defaults method to the new promisified version
|
|
117
|
+
promisifiedWithDefaults.defaults = promisifiedRequest.defaults;
|
|
118
|
+
|
|
119
|
+
return promisifiedWithDefaults;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
module.exports = promisifiedRequest;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envoy/envoy-integrations-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,12 +17,11 @@
|
|
|
17
17
|
},
|
|
18
18
|
"homepage": "https://github.com/envoy/envoy-integrations-sdk-nodejs#readme",
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"@cypress/request": "^3.0.9",
|
|
20
21
|
"axios": "^1.4.0",
|
|
21
22
|
"body-parser": "^1.19.0",
|
|
22
23
|
"dotenv": "^8.1.0",
|
|
23
|
-
"jsonwebtoken": "^9.0.0"
|
|
24
|
-
"request": "^2.88.0",
|
|
25
|
-
"request-promise-native": "^1.0.7"
|
|
24
|
+
"jsonwebtoken": "^9.0.0"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
28
27
|
"chai": "^4.2.0",
|
package/test/promises.test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const request = require('request-
|
|
1
|
+
const request = require('../lib/request-wrapper');
|
|
2
2
|
const EnvoyAPI = require('../lib/EnvoyAPI');
|
|
3
3
|
|
|
4
|
-
describe('request
|
|
4
|
+
describe('@cypress/request', () => {
|
|
5
5
|
it('default client should leak credentials in error', async () => {
|
|
6
6
|
const client = request.defaults({
|
|
7
7
|
headers: {
|
|
@@ -68,15 +68,17 @@ describe('request-promise-native', () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it('should make a successful request', async () => {
|
|
71
|
-
const response = await request('https://
|
|
72
|
-
expect(response).
|
|
71
|
+
const response = await request('https://httpstatuses.maor.io/200').catch(EnvoyAPI.safeRequestsError);
|
|
72
|
+
expect(response).toContain('200');
|
|
73
|
+
expect(response).toContain('OK');
|
|
73
74
|
});
|
|
74
75
|
|
|
75
76
|
it('should throw an error', async () => {
|
|
76
77
|
try {
|
|
77
|
-
await request('https://
|
|
78
|
+
await request('https://httpstatuses.maor.io/500').catch(EnvoyAPI.safeRequestsError);
|
|
78
79
|
} catch (error) {
|
|
79
|
-
expect(error.message).
|
|
80
|
+
expect(error.message).toContain('500');
|
|
81
|
+
expect(error.message).toContain('Internal Server Error');
|
|
80
82
|
}
|
|
81
83
|
});
|
|
82
84
|
});
|