rqlite-js 2.5.6 → 2.6.0
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/README.md +174 -155
- package/lib/api/backup/index.js +47 -47
- package/lib/api/backup/index.js.map +1 -1
- package/lib/api/backup/test.unit.js +45 -0
- package/lib/api/backup/test.unit.js.map +1 -0
- package/lib/api/backup-formats.js +16 -0
- package/lib/api/backup-formats.js.map +1 -0
- package/lib/api/client/index.js +63 -42
- package/lib/api/client/index.js.map +1 -1
- package/lib/api/client/test.unit.js +53 -0
- package/lib/api/client/test.unit.js.map +1 -0
- package/lib/api/consistency-levels.js +30 -0
- package/lib/api/consistency-levels.js.map +1 -0
- package/lib/api/data/index.js +53 -69
- package/lib/api/data/index.js.map +1 -1
- package/lib/api/data/test.unit.js +98 -0
- package/lib/api/data/test.unit.js.map +1 -0
- package/lib/api/paths.js +33 -0
- package/lib/api/paths.js.map +1 -0
- package/lib/api/query-params.js +43 -0
- package/lib/api/query-params.js.map +1 -0
- package/lib/api/results/data-result-error.js +39 -10
- package/lib/api/results/data-result-error.js.map +1 -1
- package/lib/api/results/data-result.js +57 -51
- package/lib/api/results/data-result.js.map +1 -1
- package/lib/api/results/data-results.js +50 -30
- package/lib/api/results/data-results.js.map +1 -1
- package/lib/api/results/index.js +1 -1
- package/lib/api/results/index.js.map +1 -1
- package/lib/api/results/result-fields.js +47 -0
- package/lib/api/results/result-fields.js.map +1 -0
- package/lib/api/results/test.unit.js +238 -0
- package/lib/api/results/test.unit.js.map +1 -0
- package/lib/api/status/index.js +40 -28
- package/lib/api/status/index.js.map +1 -1
- package/lib/api/status/test.unit.js +57 -0
- package/lib/api/status/test.unit.js.map +1 -0
- package/lib/http-request/auth-keys.js +15 -0
- package/lib/http-request/auth-keys.js.map +1 -0
- package/lib/http-request/content-types.js +4 -4
- package/lib/http-request/content-types.js.map +1 -1
- package/lib/http-request/errors.js.map +1 -1
- package/lib/http-request/http-headers.js +20 -0
- package/lib/http-request/http-headers.js.map +1 -0
- package/lib/http-request/http-methods.js +13 -13
- package/lib/http-request/http-methods.js.map +1 -1
- package/lib/http-request/index.js +295 -275
- package/lib/http-request/index.js.map +1 -1
- package/lib/http-request/retryable.js +6 -6
- package/lib/http-request/retryable.js.map +1 -1
- package/lib/http-request/test.unit.js +560 -0
- package/lib/http-request/test.unit.js.map +1 -0
- package/lib/index.js +31 -6
- package/lib/index.js.map +1 -1
- package/lib/test/api-data-execute-nock.js +142 -0
- package/lib/test/api-data-execute-nock.js.map +1 -0
- package/lib/test/api-data-query-nock.js +210 -0
- package/lib/test/api-data-query-nock.js.map +1 -0
- package/lib/test/backups/backup-nock.js +29 -0
- package/lib/test/backups/backup-nock.js.map +1 -0
- package/lib/test/backups/restore-nock.js +30 -0
- package/lib/test/backups/restore-nock.js.map +1 -0
- package/lib/test/env.js +15 -0
- package/lib/test/env.js.map +1 -0
- package/lib/test/unit/index.unit.js +27 -0
- package/lib/test/unit/index.unit.js.map +1 -0
- package/lib/test.integration.js +238 -0
- package/lib/test.integration.js.map +1 -0
- package/package.json +39 -27
- package/.eslintrc +0 -20
- package/.travis.yml +0 -24
- package/es6/api/backup/index.js +0 -71
- package/es6/api/client/index.js +0 -83
- package/es6/api/data/index.js +0 -123
- package/es6/api/results/data-result-error.js +0 -32
- package/es6/api/results/data-result.js +0 -134
- package/es6/api/results/data-results.js +0 -121
- package/es6/api/results/index.js +0 -7
- package/es6/api/status/index.js +0 -54
- package/es6/http-request/content-types.js +0 -4
- package/es6/http-request/errors.js +0 -16
- package/es6/http-request/http-methods.js +0 -39
- package/es6/http-request/index.js +0 -743
- package/es6/http-request/retryable.js +0 -41
- package/es6/index.js +0 -13
- package/jsconfig.json +0 -18
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports, "__esModule", { value: true });exports.DEAULT_TIMEOUT = exports.DEAULT_RETRY_DELAY = void 0;exports.createDefaultHeaders = createDefaultHeaders;exports.default = void 0;exports.getWaitTimeExponential = getWaitTimeExponential;
|
|
1
|
+
"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports, "__esModule", { value: true });exports.DEAULT_TIMEOUT = exports.DEAULT_RETRY_DELAY = void 0;exports.createDefaultHeaders = createDefaultHeaders;exports.default = void 0;exports.getWaitTimeExponential = getWaitTimeExponential;
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
var _axios = _interopRequireDefault(require("axios"));
|
|
6
7
|
var _qs = require("qs");
|
|
7
|
-
var _url = require("url");
|
|
8
8
|
var _httpMethods = require("./http-methods");
|
|
9
9
|
|
|
10
10
|
|
|
@@ -12,21 +12,24 @@ var _httpMethods = require("./http-methods");
|
|
|
12
12
|
var _contentTypes = require("./content-types");
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
var _errors = require("./errors");
|
|
17
|
-
var _retryable = require("./retryable");
|
|
18
|
-
* Plain HTTP client to be used when creating RQLite specific API HTTP clients
|
|
19
|
-
* @module http-request
|
|
20
|
-
*/
|
|
16
|
+
var _retryable = require("./retryable");
|
|
21
17
|
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var _authKeys = require("./auth-keys");
|
|
22
|
+
var _httpHeaders = require("./http-headers"); /**
|
|
23
|
+
* Plain HTTP client to be used when creating RQLite specific API HTTP clients
|
|
24
|
+
* @module http-request
|
|
25
|
+
* @see https://rqlite.io/docs/api/api/
|
|
26
|
+
*/ /**
|
|
24
27
|
* RQliteJS HTTP Request options
|
|
25
28
|
* @typedef HttpRequestOptions
|
|
26
29
|
* @type {Object}
|
|
27
30
|
* @property {Object} [auth] A object for user authentication
|
|
28
31
|
* @property {String} [auth.username] The username for authentication
|
|
29
|
-
* @property {String} [auth.password] The
|
|
32
|
+
* @property {String} [auth.password] The password for authentication
|
|
30
33
|
* @property {Object} [body] The body of the HTTP request
|
|
31
34
|
* @property {Object} [headers={}] HTTP headers to send with the request
|
|
32
35
|
* @property {String} [httpMethod=HTTP_METHOD_GET] The HTTP method for the request
|
|
@@ -35,7 +38,7 @@ var _retryable = require("./retryable");function ownKeys(object, enumerableOnly)
|
|
|
35
38
|
* @property {Boolean} [stream=false] When true the returned value is a request object with
|
|
36
39
|
* stream support instead of a request-promise result
|
|
37
40
|
* @property {Number} [timeout=DEAULT_TIMEOUT] Optional timeout to override default
|
|
38
|
-
* @property {String} uri The uri for the request which can be a relative path to use
|
|
41
|
+
* @property {String} [uri] The uri for the request which can be a relative path to use
|
|
39
42
|
* the currently active host or a full i.e. http://localhost:4001/db/query which is used
|
|
40
43
|
* literally
|
|
41
44
|
* @property {Boolean} [useLeader=false] When true the request will use the master host, the
|
|
@@ -49,30 +52,31 @@ var _retryable = require("./retryable");function ownKeys(object, enumerableOnly)
|
|
|
49
52
|
* @property {Number} [redirectAttempt=0] The current attempt based on redirect logic
|
|
50
53
|
* @property {Number} [attemptHostIndex] When in a retry state the host index of the last
|
|
51
54
|
* attempt which is used to get the next host index
|
|
55
|
+
* @property {Number} [exponentailBackoffBase] Optional exponential backoff base override
|
|
56
|
+
* @property {Number} [exponentailBackoffExponent] Optional backoff exponent override
|
|
57
|
+
* @property {Boolean} [json] Legacy option; axios uses JSON unless stream is true
|
|
52
58
|
* @property {import('http').Agent} [httpAgent] An option http agent, useful for
|
|
53
59
|
* keepalive pools using plain HTTP
|
|
54
60
|
* @property {import('https').Agent} [httpsAgent] An option http agent, useful
|
|
55
61
|
* for keepalive pools using SSL
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
/**
|
|
62
|
+
*/ /**
|
|
59
63
|
* The default timeout value
|
|
60
64
|
*/
|
|
61
|
-
const DEAULT_TIMEOUT = 30000;
|
|
65
|
+
const DEAULT_TIMEOUT = exports.DEAULT_TIMEOUT = 30000;
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
68
|
* The default to retry a request using the next host in the chain
|
|
65
|
-
*/
|
|
66
|
-
const DEAULT_RETRY_DELAY = 30000;
|
|
69
|
+
*/
|
|
70
|
+
const DEAULT_RETRY_DELAY = exports.DEAULT_RETRY_DELAY = 30000;
|
|
67
71
|
|
|
68
72
|
/**
|
|
69
73
|
* Create default header for all HTTP requests
|
|
70
74
|
* @param {Object} [headers={}] HTTP headers to send with the request
|
|
71
75
|
* @returns {Object} The headers with defaults applied
|
|
72
|
-
*/
|
|
76
|
+
*/
|
|
73
77
|
function createDefaultHeaders(headers = {}) {
|
|
74
|
-
const
|
|
75
|
-
return
|
|
78
|
+
const accept = headers[_httpHeaders.HTTP_HEADER_ACCEPT] || _contentTypes.CONTENT_TYPE_APPLICATION_JSON;
|
|
79
|
+
return { ...headers, [_httpHeaders.HTTP_HEADER_ACCEPT]: accept };
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
/**
|
|
@@ -96,7 +100,7 @@ function getWaitTimeExponential(attempt = 0, base = 100, exponent = 2) {
|
|
|
96
100
|
if (attempt === 0) {
|
|
97
101
|
return 0;
|
|
98
102
|
}
|
|
99
|
-
return
|
|
103
|
+
return exponent ** attempt * base;
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
/**
|
|
@@ -105,84 +109,82 @@ function getWaitTimeExponential(attempt = 0, base = 100, exponent = 2) {
|
|
|
105
109
|
* server
|
|
106
110
|
*/
|
|
107
111
|
class HttpRequest {
|
|
112
|
+
/**
|
|
113
|
+
* The index of the host in this.hosts which will be tried
|
|
114
|
+
* first before attempting other hosts
|
|
115
|
+
* @type {Number}
|
|
116
|
+
*/
|
|
117
|
+
activeHostIndex = 0;
|
|
108
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Whether or not the setNextActiveHostIndex() should
|
|
121
|
+
* perform a round robin strategy
|
|
122
|
+
*/
|
|
123
|
+
activeHostRoundRobin = true;
|
|
109
124
|
|
|
125
|
+
/**
|
|
126
|
+
* The regex pattern to check if a uri is absolute or relative,
|
|
127
|
+
* if it is absolute the host is not appended
|
|
128
|
+
*/
|
|
129
|
+
absoluteUriPattern = /^https?:\/\//;
|
|
110
130
|
|
|
131
|
+
/**
|
|
132
|
+
* A list of hosts that are tried in round robin fashion
|
|
133
|
+
* when certain HTTP responses are received
|
|
134
|
+
* @type {String[]}
|
|
135
|
+
*/
|
|
136
|
+
hosts = [];
|
|
111
137
|
|
|
138
|
+
/**
|
|
139
|
+
* @type {import('http').Agent} The http agent if it is set
|
|
140
|
+
*/
|
|
141
|
+
httpAgent;
|
|
112
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @type {import('https').Agent} The https agent if it is set
|
|
145
|
+
*/
|
|
146
|
+
httpsAgent;
|
|
113
147
|
|
|
148
|
+
/**
|
|
149
|
+
* The host list index of the leader node defaults
|
|
150
|
+
* to the first host
|
|
151
|
+
* @type {Number}
|
|
152
|
+
*/
|
|
153
|
+
leaderHostIndex = 0;
|
|
114
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Http error codes which are considered retryable
|
|
157
|
+
* @type {Set<String>}
|
|
158
|
+
*/
|
|
159
|
+
retryableErrorCodes = _retryable.RETRYABLE_ERROR_CODES;
|
|
115
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Http status codes which are considered retryable
|
|
163
|
+
* @type {Set<Number>}
|
|
164
|
+
*/
|
|
165
|
+
retryableStatusCodes = _retryable.RETRYABLE_STATUS_CODES;
|
|
116
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Http methods which are considered retryable
|
|
169
|
+
* @type {Set<String>}
|
|
170
|
+
*/
|
|
171
|
+
retryableHttpMethods = _retryable.RETRYABLE_HTTP_METHODS;
|
|
117
172
|
|
|
173
|
+
/**
|
|
174
|
+
* The exponential backoff base for retries
|
|
175
|
+
*/
|
|
176
|
+
exponentailBackoffBase = 100;
|
|
118
177
|
|
|
178
|
+
/**
|
|
179
|
+
* The exponent to increase backoff each try
|
|
180
|
+
*/
|
|
181
|
+
exponentailBackoffExponent = 1.1;
|
|
119
182
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Authentication Map
|
|
185
|
+
* @type {Map<String, String>}
|
|
186
|
+
*/
|
|
187
|
+
authentication = new Map();
|
|
186
188
|
|
|
187
189
|
/**
|
|
188
190
|
* Construtor for HttpRequest
|
|
@@ -206,53 +208,53 @@ class HttpRequest {
|
|
|
206
208
|
* for retry exponential backoff
|
|
207
209
|
* @param {Number} [options.exponentailBackoffExponent] Exponent to increase backoff each try
|
|
208
210
|
*/
|
|
209
|
-
constructor(hosts, options = {}) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
Array.isArray(retryableStatusCodes) ? Set(retryableStatusCodes) : retryableStatusCodes
|
|
211
|
+
constructor(hosts, options = {}) {
|
|
212
|
+
this.setHosts(hosts);
|
|
213
|
+
if (this.getTotalHosts() === 0) {
|
|
214
|
+
throw new Error('At least one host must be provided');
|
|
215
|
+
}
|
|
216
|
+
const {
|
|
217
|
+
activeHostRoundRobin = true,
|
|
218
|
+
httpAgent,
|
|
219
|
+
httpsAgent,
|
|
220
|
+
retryableErrorCodes,
|
|
221
|
+
retryableStatusCodes,
|
|
222
|
+
retryableHttpMethods,
|
|
223
|
+
exponentailBackoffExponent,
|
|
224
|
+
exponentailBackoffBase,
|
|
225
|
+
authentication
|
|
226
|
+
} = options;
|
|
227
|
+
if (typeof authentication === 'object') {
|
|
228
|
+
const { username, password } = authentication;
|
|
229
|
+
if (username) {
|
|
230
|
+
this.authentication.set(_authKeys.AUTH_USERNAME, username);
|
|
231
|
+
}
|
|
232
|
+
if (password) {
|
|
233
|
+
this.authentication.set(_authKeys.AUTH_PASSWORD, password);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (typeof activeHostRoundRobin !== 'undefined') {
|
|
237
|
+
this.setActiveHostRoundRobin(activeHostRoundRobin);
|
|
238
|
+
}
|
|
239
|
+
if (typeof httpAgent !== 'undefined') {
|
|
240
|
+
this.setHttpAgent(httpAgent);
|
|
241
|
+
}
|
|
242
|
+
if (typeof httpsAgent !== 'undefined') {
|
|
243
|
+
this.setHttpsAgent(httpsAgent);
|
|
244
|
+
}
|
|
245
|
+
if (retryableErrorCodes instanceof Set || Array.isArray(retryableErrorCodes)) {
|
|
246
|
+
this.setRetryableErrorCodes(
|
|
247
|
+
Array.isArray(retryableErrorCodes) ? new Set(retryableErrorCodes) : retryableErrorCodes
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
if (retryableStatusCodes instanceof Set || Array.isArray(retryableStatusCodes)) {
|
|
251
|
+
this.setRetryableStatusCodes(
|
|
252
|
+
Array.isArray(retryableStatusCodes) ? new Set(retryableStatusCodes) : retryableStatusCodes
|
|
251
253
|
);
|
|
252
254
|
}
|
|
253
255
|
if (retryableHttpMethods instanceof Set || Array.isArray(retryableHttpMethods)) {
|
|
254
256
|
this.setRetryableHttpMethods(
|
|
255
|
-
Array.isArray(retryableHttpMethods) ? Set(retryableHttpMethods) : retryableHttpMethods
|
|
257
|
+
Array.isArray(retryableHttpMethods) ? new Set(retryableHttpMethods) : retryableHttpMethods
|
|
256
258
|
);
|
|
257
259
|
}
|
|
258
260
|
if (Number.isFinite(exponentailBackoffBase)) {
|
|
@@ -270,12 +272,12 @@ class HttpRequest {
|
|
|
270
272
|
* @param {String} [authentication.password] The host authentication password
|
|
271
273
|
*/
|
|
272
274
|
setAuthentication(authentication = {}) {
|
|
273
|
-
const
|
|
275
|
+
const { username, password } = authentication;
|
|
274
276
|
if (username) {
|
|
275
|
-
this.authentication.set(
|
|
277
|
+
this.authentication.set(_authKeys.AUTH_USERNAME, username);
|
|
276
278
|
}
|
|
277
279
|
if (password) {
|
|
278
|
-
this.authentication.set(
|
|
280
|
+
this.authentication.set(_authKeys.AUTH_PASSWORD, password);
|
|
279
281
|
}
|
|
280
282
|
}
|
|
281
283
|
|
|
@@ -289,7 +291,7 @@ class HttpRequest {
|
|
|
289
291
|
|
|
290
292
|
/**
|
|
291
293
|
* Get the exponentail backoff base
|
|
292
|
-
* @
|
|
294
|
+
* @returns {Number} The exponentail backoff base
|
|
293
295
|
*/
|
|
294
296
|
getExponentailBackoffBase() {
|
|
295
297
|
return this.exponentailBackoffBase;
|
|
@@ -305,7 +307,7 @@ class HttpRequest {
|
|
|
305
307
|
|
|
306
308
|
/**
|
|
307
309
|
* Get the exponentail backoff exponent
|
|
308
|
-
* @
|
|
310
|
+
* @returns {Number} The exponentail backoff exponent
|
|
309
311
|
*/
|
|
310
312
|
getExponentailBackoffExponent() {
|
|
311
313
|
return this.exponentailBackoffExponent;
|
|
@@ -313,7 +315,7 @@ class HttpRequest {
|
|
|
313
315
|
|
|
314
316
|
/**
|
|
315
317
|
* Set the retryable error codes
|
|
316
|
-
* @param {Set} retryableErrorCodes
|
|
318
|
+
* @param {Set<String>} retryableErrorCodes
|
|
317
319
|
*/
|
|
318
320
|
setRetryableErrorCodes(retryableErrorCodes) {
|
|
319
321
|
this.retryableErrorCodes = retryableErrorCodes;
|
|
@@ -321,7 +323,7 @@ class HttpRequest {
|
|
|
321
323
|
|
|
322
324
|
/**
|
|
323
325
|
* Get the retryable error codes
|
|
324
|
-
* @returns {Set}
|
|
326
|
+
* @returns {Set<String>}
|
|
325
327
|
*/
|
|
326
328
|
getRetryableErrorCodes() {
|
|
327
329
|
return this.retryableErrorCodes;
|
|
@@ -329,7 +331,7 @@ class HttpRequest {
|
|
|
329
331
|
|
|
330
332
|
/**
|
|
331
333
|
* Set the retryable status codes
|
|
332
|
-
* @param {Set} retryableStatusCodes
|
|
334
|
+
* @param {Set<Number>} retryableStatusCodes
|
|
333
335
|
*/
|
|
334
336
|
setRetryableStatusCodes(retryableStatusCodes) {
|
|
335
337
|
this.retryableStatusCodes = retryableStatusCodes;
|
|
@@ -337,7 +339,7 @@ class HttpRequest {
|
|
|
337
339
|
|
|
338
340
|
/**
|
|
339
341
|
* Get the retryable status codes
|
|
340
|
-
* @returns {Set}
|
|
342
|
+
* @returns {Set<Number>}
|
|
341
343
|
*/
|
|
342
344
|
getRetryableStatusCodes() {
|
|
343
345
|
return this.retryableStatusCodes;
|
|
@@ -345,7 +347,7 @@ class HttpRequest {
|
|
|
345
347
|
|
|
346
348
|
/**
|
|
347
349
|
* Set the retryable http methods
|
|
348
|
-
* @param {Set} retryableHttpMethods
|
|
350
|
+
* @param {Set<String>} retryableHttpMethods
|
|
349
351
|
*/
|
|
350
352
|
setRetryableHttpMethods(retryableHttpMethods) {
|
|
351
353
|
this.retryableHttpMethods = retryableHttpMethods;
|
|
@@ -353,7 +355,7 @@ class HttpRequest {
|
|
|
353
355
|
|
|
354
356
|
/**
|
|
355
357
|
* Get the retryable http methods
|
|
356
|
-
* @returns {Set}
|
|
358
|
+
* @returns {Set<String>}
|
|
357
359
|
*/
|
|
358
360
|
getRetryableHttpMethods() {
|
|
359
361
|
return this.retryableHttpMethods;
|
|
@@ -423,11 +425,22 @@ class HttpRequest {
|
|
|
423
425
|
* @returns {Number} The found host index or -1 if not found
|
|
424
426
|
*/
|
|
425
427
|
findHostIndex(host) {
|
|
426
|
-
|
|
428
|
+
let parsedHostToFind;
|
|
429
|
+
try {
|
|
430
|
+
parsedHostToFind = new URL(host);
|
|
431
|
+
} catch (e) {
|
|
432
|
+
return -1;
|
|
433
|
+
}
|
|
427
434
|
return this.getHosts().findIndex((v) => {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
435
|
+
try {
|
|
436
|
+
const parsedHost = new URL(v);
|
|
437
|
+
// Find a host where all the parsed fields match the requested host
|
|
438
|
+
return ['hostname', 'protocol', 'port', 'pathname'].every(
|
|
439
|
+
(field) => parsedHostToFind[field] === parsedHost[field]
|
|
440
|
+
);
|
|
441
|
+
} catch (e) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
431
444
|
});
|
|
432
445
|
}
|
|
433
446
|
|
|
@@ -570,18 +583,18 @@ class HttpRequest {
|
|
|
570
583
|
|
|
571
584
|
/**
|
|
572
585
|
* Returns true when the HTTP request is retryable
|
|
573
|
-
* @param {Object} options The options
|
|
574
|
-
* @param {Number} options.statusCode The HTTP status code
|
|
575
|
-
* @param {String} options.errorCode The error code
|
|
576
|
-
* @param {String} options.httpMethod The http method
|
|
586
|
+
* @param {Object} [options={}] The options
|
|
587
|
+
* @param {Number} [options.statusCode] The HTTP status code
|
|
588
|
+
* @param {String} [options.errorCode] The error code
|
|
589
|
+
* @param {String} [options.httpMethod] The http method
|
|
577
590
|
* @returns {Boolean} True if the request is retry able
|
|
578
591
|
*/
|
|
579
592
|
requestIsRetryable(options = {}) {
|
|
580
|
-
const
|
|
581
|
-
statusCode
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
593
|
+
const {
|
|
594
|
+
statusCode,
|
|
595
|
+
errorCode,
|
|
596
|
+
httpMethod
|
|
597
|
+
} = options;
|
|
585
598
|
// Honor strictly the http method
|
|
586
599
|
if (!this.getRetryableHttpMethods().has(httpMethod)) {
|
|
587
600
|
return false;
|
|
@@ -602,143 +615,150 @@ class HttpRequest {
|
|
|
602
615
|
* property when stream is false and a stream when the stream option is true
|
|
603
616
|
* @throws {ERROR_HTTP_REQUEST_MAX_REDIRECTS} When the maximum number of redirect has been reached
|
|
604
617
|
*/
|
|
605
|
-
fetch(options = {}) {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
618
|
+
async fetch(options = {}) {
|
|
619
|
+
const {
|
|
620
|
+
body,
|
|
621
|
+
headers = {},
|
|
622
|
+
httpMethod = _httpMethods.HTTP_METHOD_GET,
|
|
623
|
+
query,
|
|
624
|
+
stream = false,
|
|
625
|
+
timeout = DEAULT_TIMEOUT,
|
|
626
|
+
useLeader = false,
|
|
627
|
+
retries = this.getTotalHosts() * 3,
|
|
628
|
+
maxRedirects = 10,
|
|
629
|
+
attempt = 0,
|
|
630
|
+
retryAttempt = 0,
|
|
631
|
+
redirectAttempt = 0,
|
|
632
|
+
attemptHostIndex,
|
|
633
|
+
exponentailBackoffExponent = this.getExponentailBackoffExponent(),
|
|
634
|
+
exponentailBackoffBase = this.getExponentailBackoffBase(),
|
|
635
|
+
httpAgent = this.getHttpAgent(),
|
|
636
|
+
httpsAgent = this.getHttpsAgent()
|
|
637
|
+
} = options;
|
|
638
|
+
// Honor the supplied attemptHostIndex or get the active host
|
|
639
|
+
const activeHost = Number.isFinite(attemptHostIndex) ? this.getHosts()[attemptHostIndex] :
|
|
640
|
+
this.getActiveHost(useLeader);
|
|
641
|
+
let { uri } = options;
|
|
642
|
+
if (!uri) {
|
|
643
|
+
throw new Error('The uri option is required');
|
|
644
|
+
}
|
|
645
|
+
uri = this.uriIsAbsolute(uri) ? uri : `${activeHost}/${cleanPath(uri)}`;
|
|
646
|
+
try {
|
|
647
|
+
let auth;
|
|
648
|
+
if (this.authentication.size) {
|
|
649
|
+
auth = {
|
|
650
|
+
[_authKeys.AUTH_USERNAME]: this.authentication.get(_authKeys.AUTH_USERNAME),
|
|
651
|
+
[_authKeys.AUTH_PASSWORD]: this.authentication.get(_authKeys.AUTH_PASSWORD)
|
|
652
|
+
};
|
|
631
653
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
headers: createDefaultHeaders(headers),
|
|
647
|
-
responseType: stream ? 'stream' : 'json',
|
|
648
|
-
method: httpMethod,
|
|
649
|
-
params: query,
|
|
650
|
-
timeout,
|
|
651
|
-
httpsAgent,
|
|
652
|
-
httpAgent,
|
|
653
|
-
paramsSerializer(params) {
|
|
654
|
-
return (0, _qs.stringify)(params, { arrayFormat: 'brackets' });
|
|
655
|
-
}
|
|
656
|
-
});
|
|
657
|
-
if (stream) {
|
|
658
|
-
return response.data;
|
|
654
|
+
const response = await (0, _axios.default)({
|
|
655
|
+
url: uri,
|
|
656
|
+
auth,
|
|
657
|
+
data: body,
|
|
658
|
+
maxRedirects: 0, // Handle redirects manually to allow reposting data
|
|
659
|
+
headers: createDefaultHeaders(headers),
|
|
660
|
+
responseType: stream ? 'stream' : 'json',
|
|
661
|
+
method: httpMethod,
|
|
662
|
+
params: query,
|
|
663
|
+
timeout,
|
|
664
|
+
httpsAgent,
|
|
665
|
+
httpAgent,
|
|
666
|
+
paramsSerializer(params) {
|
|
667
|
+
return (0, _qs.stringify)(params, { arrayFormat: 'brackets' });
|
|
659
668
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
669
|
+
});
|
|
670
|
+
if (stream) {
|
|
671
|
+
return response.data;
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
body: response.data,
|
|
675
|
+
status: response.status
|
|
676
|
+
};
|
|
677
|
+
} catch (e) {
|
|
678
|
+
const { response = {}, code: errorCode } = e;
|
|
679
|
+
const { status: responseStatus, headers: responseHeaders = {} } = response;
|
|
680
|
+
// Check if the error was a redirect
|
|
681
|
+
const retryable = this.requestIsRetryable({
|
|
682
|
+
statusCode: responseStatus,
|
|
683
|
+
errorCode,
|
|
684
|
+
httpMethod
|
|
685
|
+
});
|
|
686
|
+
// Save the next active host index and pass it to retry manually
|
|
687
|
+
let nextAttemptHostIndex = Number.isFinite(attemptHostIndex) ? attemptHostIndex :
|
|
688
|
+
this.getActiveHostIndex();
|
|
689
|
+
nextAttemptHostIndex += 1;
|
|
690
|
+
// We go past the last index start from zero
|
|
691
|
+
if (nextAttemptHostIndex === this.getTotalHosts()) {
|
|
692
|
+
nextAttemptHostIndex = 0;
|
|
693
|
+
}
|
|
694
|
+
// First check if this is a redirect error
|
|
695
|
+
if (responseStatus === 301 || responseStatus === 302) {
|
|
696
|
+
// We maxed out on redirect attempts
|
|
697
|
+
if (redirectAttempt >= maxRedirects) {
|
|
698
|
+
throw new _errors.ERROR_HTTP_REQUEST_MAX_REDIRECTS(`The maximum number of redirects ${maxRedirects} has been reached`);
|
|
680
699
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
const
|
|
688
|
-
// If
|
|
689
|
-
if (
|
|
690
|
-
|
|
691
|
-
// If the redirect exists in the hosts list remember it for next time
|
|
692
|
-
if (newLeaderHostIndex > -1) {
|
|
693
|
-
_this.setLeaderHostIndex(newLeaderHostIndex);
|
|
694
|
-
}
|
|
700
|
+
const location = typeof responseHeaders === 'object' ?
|
|
701
|
+
responseHeaders[_httpHeaders.HTTP_HEADER_LOCATION.toLowerCase()] ||
|
|
702
|
+
responseHeaders[_httpHeaders.HTTP_HEADER_LOCATION] :
|
|
703
|
+
undefined;
|
|
704
|
+
// If we were asked to use the leader, but got redirect the leader moved so remember it
|
|
705
|
+
if (useLeader) {
|
|
706
|
+
const newLeaderHostIndex = this.findHostIndex(location);
|
|
707
|
+
// If the redirect exists in the hosts list remember it for next time
|
|
708
|
+
if (newLeaderHostIndex > -1) {
|
|
709
|
+
this.setLeaderHostIndex(newLeaderHostIndex);
|
|
695
710
|
}
|
|
696
|
-
return _this.fetch(_objectSpread(_objectSpread({},
|
|
697
|
-
options), {}, {
|
|
698
|
-
uri: location,
|
|
699
|
-
attempt: attempt + 1,
|
|
700
|
-
redirectAttempt: redirectAttempt + 1,
|
|
701
|
-
attemptHostIndex: nextAttemptHostIndex })
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
if (retryable && retryAttempt < retries) {
|
|
705
|
-
const waitTime = getWaitTimeExponential(
|
|
706
|
-
retryAttempt,
|
|
707
|
-
exponentailBackoffBase,
|
|
708
|
-
exponentailBackoffExponent
|
|
709
|
-
);
|
|
710
|
-
yield new Promise((resolve) => {
|
|
711
|
-
setTimeout(() => {
|
|
712
|
-
resolve(undefined);
|
|
713
|
-
}, waitTime);
|
|
714
|
-
});
|
|
715
|
-
return _this.fetch(_objectSpread(_objectSpread({},
|
|
716
|
-
options), {}, {
|
|
717
|
-
attempt: attempt + 1,
|
|
718
|
-
retryAttempt: retryAttempt + 1,
|
|
719
|
-
attemptHostIndex: nextAttemptHostIndex })
|
|
720
|
-
);
|
|
721
711
|
}
|
|
722
|
-
|
|
723
|
-
|
|
712
|
+
return this.fetch({
|
|
713
|
+
...options,
|
|
714
|
+
uri: location,
|
|
715
|
+
attempt: attempt + 1,
|
|
716
|
+
redirectAttempt: redirectAttempt + 1,
|
|
717
|
+
attemptHostIndex: nextAttemptHostIndex
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
if (retryable && retryAttempt < retries) {
|
|
721
|
+
const waitTime = getWaitTimeExponential(
|
|
722
|
+
retryAttempt,
|
|
723
|
+
exponentailBackoffBase,
|
|
724
|
+
exponentailBackoffExponent
|
|
725
|
+
);
|
|
726
|
+
await new Promise((resolve) => {
|
|
727
|
+
setTimeout(() => {
|
|
728
|
+
resolve(undefined);
|
|
729
|
+
}, waitTime);
|
|
730
|
+
});
|
|
731
|
+
return this.fetch({
|
|
732
|
+
...options,
|
|
733
|
+
attempt: attempt + 1,
|
|
734
|
+
retryAttempt: retryAttempt + 1,
|
|
735
|
+
attemptHostIndex: nextAttemptHostIndex
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
throw e;
|
|
739
|
+
}
|
|
724
740
|
}
|
|
725
741
|
|
|
726
742
|
/**
|
|
727
743
|
* Perform an HTTP GET request
|
|
728
|
-
* @param {
|
|
729
|
-
* @
|
|
744
|
+
* @param {...*} args HttpRequestOptions, or (path, sql, options) when overridden by ApiClient
|
|
745
|
+
* @returns {Promise<*>}
|
|
746
|
+
* @see HttpRequest#fetch
|
|
730
747
|
*/
|
|
731
|
-
get(
|
|
732
|
-
|
|
748
|
+
async get(...args) {
|
|
749
|
+
const options = args[0] || {};
|
|
750
|
+
return this.fetch({ ...options, httpMethod: _httpMethods.HTTP_METHOD_GET });
|
|
733
751
|
}
|
|
734
752
|
|
|
735
753
|
/**
|
|
736
754
|
* Perform an HTTP POST request
|
|
737
|
-
* @param {
|
|
738
|
-
* @
|
|
755
|
+
* @param {...*} args HttpRequestOptions, or (path, sql, options) when overridden by ApiClient
|
|
756
|
+
* @returns {Promise<*>}
|
|
757
|
+
* @see HttpRequest#fetch
|
|
739
758
|
*/
|
|
740
|
-
post(
|
|
741
|
-
|
|
759
|
+
async post(...args) {
|
|
760
|
+
const options = args[0] || {};
|
|
761
|
+
return this.fetch({ ...options, httpMethod: _httpMethods.HTTP_METHOD_POST });
|
|
742
762
|
}
|
|
743
763
|
}exports.default = HttpRequest;
|
|
744
764
|
//# sourceMappingURL=index.js.map
|