@appliqation/automation-sdk 2.1.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/LICENSE +21 -0
- package/README.md +441 -0
- package/package.json +107 -0
- package/src/AppliqationClient.js +562 -0
- package/src/constants.js +245 -0
- package/src/core/AuthManager.js +353 -0
- package/src/core/HttpClient.js +475 -0
- package/src/index.d.ts +333 -0
- package/src/index.js +26 -0
- package/src/playwright/JwtBrowserAuth.js +240 -0
- package/src/playwright/fixture.js +92 -0
- package/src/playwright/global-setup.js +243 -0
- package/src/playwright/helpers/jwt-browser-auth.js +227 -0
- package/src/playwright/index.js +16 -0
- package/src/reporters/cypress/CypressReporter.js +387 -0
- package/src/reporters/cypress/UuidExtractor.js +139 -0
- package/src/reporters/cypress/index.js +30 -0
- package/src/reporters/jest/JestReporter.js +361 -0
- package/src/reporters/jest/UuidExtractor.js +174 -0
- package/src/reporters/jest/index.js +28 -0
- package/src/reporters/playwright/AppliqationReporter.js +654 -0
- package/src/reporters/playwright/helpers/DeviceOsDetector.js +435 -0
- package/src/reporters/playwright/helpers/UuidExtractor.js +290 -0
- package/src/reporters/playwright/index.d.ts +96 -0
- package/src/reporters/playwright/index.js +14 -0
- package/src/services/OrphanTestService.js +74 -0
- package/src/services/ResultService.js +252 -0
- package/src/services/RunMatrixService.js +309 -0
- package/src/utils/PayloadBuilder.js +280 -0
- package/src/utils/RunDataNormalizer.js +335 -0
- package/src/utils/UuidValidator.js +102 -0
- package/src/utils/errors.js +217 -0
- package/src/utils/index.js +17 -0
- package/src/utils/logger.js +124 -0
- package/src/utils/mapAppqUuid.js +83 -0
- package/src/utils/validator.js +157 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const logger = require('../utils/logger');
|
|
5
|
+
const {
|
|
6
|
+
DEFAULT_TIMEOUT,
|
|
7
|
+
DEFAULT_RETRIES,
|
|
8
|
+
DEFAULT_RETRY_DELAY,
|
|
9
|
+
MAX_RETRY_DELAY,
|
|
10
|
+
RETRY_JITTER_FACTOR,
|
|
11
|
+
BACKOFF_MULTIPLIER,
|
|
12
|
+
DEFAULT_KEEP_ALIVE,
|
|
13
|
+
DEFAULT_MAX_SOCKETS,
|
|
14
|
+
DEFAULT_MAX_FREE_SOCKETS,
|
|
15
|
+
DEFAULT_KEEP_ALIVE_MSECS,
|
|
16
|
+
HTTP_TOO_MANY_REQUESTS,
|
|
17
|
+
HTTP_REQUEST_TIMEOUT,
|
|
18
|
+
HTTP_SERVER_ERROR_THRESHOLD
|
|
19
|
+
} = require('../constants');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generic HTTP client for making requests to Appliqation API
|
|
23
|
+
*/
|
|
24
|
+
class HttpClient {
|
|
25
|
+
constructor(config, auth = null) {
|
|
26
|
+
this.config = {
|
|
27
|
+
baseUrl: config.baseUrl,
|
|
28
|
+
timeout: config.timeout || DEFAULT_TIMEOUT,
|
|
29
|
+
retries: config.retries || DEFAULT_RETRIES,
|
|
30
|
+
retryDelay: config.retryDelay || DEFAULT_RETRY_DELAY,
|
|
31
|
+
rejectUnauthorized: config.rejectUnauthorized !== undefined ? config.rejectUnauthorized : true, // Default to secure
|
|
32
|
+
// Connection pooling settings
|
|
33
|
+
keepAlive: config.keepAlive !== undefined ? config.keepAlive : DEFAULT_KEEP_ALIVE,
|
|
34
|
+
maxSockets: config.maxSockets || DEFAULT_MAX_SOCKETS,
|
|
35
|
+
maxFreeSockets: config.maxFreeSockets || DEFAULT_MAX_FREE_SOCKETS,
|
|
36
|
+
keepAliveMsecs: config.keepAliveMsecs || DEFAULT_KEEP_ALIVE_MSECS,
|
|
37
|
+
...config
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Validate required baseUrl
|
|
41
|
+
if (!this.config.baseUrl) {
|
|
42
|
+
throw new Error('baseUrl is required. Please set APPLIQATION_BASE_URL environment variable or provide baseUrl in configuration.');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Store auth manager reference
|
|
46
|
+
this.auth = auth;
|
|
47
|
+
|
|
48
|
+
// Create HTTP/HTTPS agents with connection pooling
|
|
49
|
+
const agentOptions = {
|
|
50
|
+
keepAlive: this.config.keepAlive,
|
|
51
|
+
maxSockets: this.config.maxSockets,
|
|
52
|
+
maxFreeSockets: this.config.maxFreeSockets,
|
|
53
|
+
keepAliveMsecs: this.config.keepAliveMsecs,
|
|
54
|
+
rejectUnauthorized: this.config.rejectUnauthorized
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
this.httpAgent = new http.Agent(agentOptions);
|
|
58
|
+
this.httpsAgent = new https.Agent(agentOptions);
|
|
59
|
+
|
|
60
|
+
logger.debug('HTTP connection pooling configured', {
|
|
61
|
+
keepAlive: agentOptions.keepAlive,
|
|
62
|
+
maxSockets: agentOptions.maxSockets,
|
|
63
|
+
maxFreeSockets: agentOptions.maxFreeSockets
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.axios = axios.create({
|
|
67
|
+
baseURL: this.config.baseUrl,
|
|
68
|
+
timeout: this.config.timeout,
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
'Accept': 'application/json'
|
|
72
|
+
},
|
|
73
|
+
// Use connection pooling agents
|
|
74
|
+
httpAgent: this.httpAgent,
|
|
75
|
+
httpsAgent: this.httpsAgent
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
this.setupInterceptors();
|
|
79
|
+
|
|
80
|
+
// Set API key if provided in config
|
|
81
|
+
if (this.config.apiKey) {
|
|
82
|
+
this.setApiKey(this.config.apiKey);
|
|
83
|
+
logger.debug('API key set in HttpClient');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
setupInterceptors() {
|
|
88
|
+
// Response interceptor for error handling and JWT refresh
|
|
89
|
+
this.axios.interceptors.response.use(
|
|
90
|
+
(response) => response,
|
|
91
|
+
async (error) => {
|
|
92
|
+
const originalRequest = error.config;
|
|
93
|
+
|
|
94
|
+
// Handle 401 errors with automatic JWT token refresh
|
|
95
|
+
if (error.response?.status === 401 &&
|
|
96
|
+
this.auth &&
|
|
97
|
+
this.auth.hasApiKey() &&
|
|
98
|
+
!originalRequest._retry) {
|
|
99
|
+
|
|
100
|
+
// Mark this request as already retried to prevent infinite loops
|
|
101
|
+
originalRequest._retry = true;
|
|
102
|
+
|
|
103
|
+
logger.info('401 Unauthorized detected - attempting JWT token refresh...', {
|
|
104
|
+
url: originalRequest.url,
|
|
105
|
+
method: originalRequest.method
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
// Attempt to refresh JWT token using AuthManager
|
|
110
|
+
await this.auth.refreshJwtToken();
|
|
111
|
+
|
|
112
|
+
logger.info('JWT token refreshed successfully, retrying original request');
|
|
113
|
+
|
|
114
|
+
// Retry the original request with the new token
|
|
115
|
+
return this.axios(originalRequest);
|
|
116
|
+
} catch (refreshError) {
|
|
117
|
+
logger.error('Failed to refresh JWT token', {
|
|
118
|
+
error: refreshError.message,
|
|
119
|
+
originalUrl: originalRequest.url
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// If refresh fails, reject with the refresh error
|
|
123
|
+
return Promise.reject(refreshError);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// For non-401 errors or when refresh is not applicable, log and reject
|
|
128
|
+
if (error.response?.status === 401) {
|
|
129
|
+
logger.warn('Authentication failed (401) - JWT refresh not available or already attempted');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return Promise.reject(error);
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Make a GET request
|
|
139
|
+
* @param {string} url - The URL path
|
|
140
|
+
* @param {Object} config - Axios config options
|
|
141
|
+
* @returns {Promise<Object>} Response data
|
|
142
|
+
*/
|
|
143
|
+
async get(url, config = {}) {
|
|
144
|
+
try {
|
|
145
|
+
logger.debug(`GET ${url}`);
|
|
146
|
+
const response = await this.retryRequest(() =>
|
|
147
|
+
this.axios.get(url, config)
|
|
148
|
+
);
|
|
149
|
+
return {
|
|
150
|
+
success: true,
|
|
151
|
+
data: response.data,
|
|
152
|
+
status: response.status,
|
|
153
|
+
headers: response.headers
|
|
154
|
+
};
|
|
155
|
+
} catch (error) {
|
|
156
|
+
return this.handleError(error, 'GET', url);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Make a POST request
|
|
162
|
+
* @param {string} url - The URL path
|
|
163
|
+
* @param {Object} data - Request body
|
|
164
|
+
* @param {Object} config - Axios config options
|
|
165
|
+
* @returns {Promise<Object>} Response data
|
|
166
|
+
*/
|
|
167
|
+
async post(url, data, config = {}) {
|
|
168
|
+
const startTime = Date.now();
|
|
169
|
+
try {
|
|
170
|
+
logger.debug(`POST ${url}`, { dataSize: JSON.stringify(data).length });
|
|
171
|
+
logger.debug(`POST request starting at ${new Date().toISOString()}`);
|
|
172
|
+
|
|
173
|
+
// Detailed logging for debugging project key issues
|
|
174
|
+
logger.debug(`POST ${url} - Request Body:`, JSON.stringify(data, null, 2));
|
|
175
|
+
logger.debug(`POST ${url} - Request Headers:`, JSON.stringify(this.axios.defaults.headers.common, null, 2));
|
|
176
|
+
|
|
177
|
+
const response = await this.retryRequest(() =>
|
|
178
|
+
this.axios.post(url, data, config)
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const duration = Date.now() - startTime;
|
|
182
|
+
logger.debug(`POST ${url} completed in ${duration}ms`, {
|
|
183
|
+
status: response.status,
|
|
184
|
+
timestamp: new Date().toISOString()
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Detailed response logging
|
|
188
|
+
logger.debug(`POST ${url} - Response Status: ${response.status}`);
|
|
189
|
+
logger.debug(`POST ${url} - Response Body:`, JSON.stringify(response.data, null, 2));
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
success: true,
|
|
193
|
+
data: response.data,
|
|
194
|
+
status: response.status,
|
|
195
|
+
headers: response.headers
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
const duration = Date.now() - startTime;
|
|
199
|
+
logger.error(`POST ${url} failed after ${duration}ms`);
|
|
200
|
+
logger.error(`POST ${url} - Error Details:`, {
|
|
201
|
+
message: error.message,
|
|
202
|
+
status: error.response?.status,
|
|
203
|
+
statusText: error.response?.statusText,
|
|
204
|
+
responseData: error.response?.data
|
|
205
|
+
});
|
|
206
|
+
return this.handleError(error, 'POST', url);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Make a PUT request
|
|
212
|
+
* @param {string} url - The URL path
|
|
213
|
+
* @param {Object} data - Request body
|
|
214
|
+
* @param {Object} config - Axios config options
|
|
215
|
+
* @returns {Promise<Object>} Response data
|
|
216
|
+
*/
|
|
217
|
+
async put(url, data, config = {}) {
|
|
218
|
+
try {
|
|
219
|
+
logger.debug(`PUT ${url}`);
|
|
220
|
+
const response = await this.retryRequest(() =>
|
|
221
|
+
this.axios.put(url, data, config)
|
|
222
|
+
);
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
data: response.data,
|
|
226
|
+
status: response.status,
|
|
227
|
+
headers: response.headers
|
|
228
|
+
};
|
|
229
|
+
} catch (error) {
|
|
230
|
+
return this.handleError(error, 'PUT', url);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Make a DELETE request
|
|
236
|
+
* @param {string} url - The URL path
|
|
237
|
+
* @param {Object} config - Axios config options
|
|
238
|
+
* @returns {Promise<Object>} Response data
|
|
239
|
+
*/
|
|
240
|
+
async delete(url, config = {}) {
|
|
241
|
+
try {
|
|
242
|
+
logger.debug(`DELETE ${url}`);
|
|
243
|
+
const response = await this.retryRequest(() =>
|
|
244
|
+
this.axios.delete(url, config)
|
|
245
|
+
);
|
|
246
|
+
return {
|
|
247
|
+
success: true,
|
|
248
|
+
data: response.data,
|
|
249
|
+
status: response.status,
|
|
250
|
+
headers: response.headers
|
|
251
|
+
};
|
|
252
|
+
} catch (error) {
|
|
253
|
+
return this.handleError(error, 'DELETE', url);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Set authorization header
|
|
259
|
+
* @param {string} token - Authorization token
|
|
260
|
+
*/
|
|
261
|
+
setAuthToken(token) {
|
|
262
|
+
if (token) {
|
|
263
|
+
this.axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
264
|
+
} else {
|
|
265
|
+
delete this.axios.defaults.headers.common['Authorization'];
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Set API key header
|
|
271
|
+
* @param {string} apiKey - API key
|
|
272
|
+
*/
|
|
273
|
+
setApiKey(apiKey) {
|
|
274
|
+
if (apiKey) {
|
|
275
|
+
this.axios.defaults.headers.common['X-API-Key'] = apiKey;
|
|
276
|
+
} else {
|
|
277
|
+
delete this.axios.defaults.headers.common['X-API-Key'];
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Set custom header
|
|
283
|
+
* @param {string} key - Header name
|
|
284
|
+
* @param {string} value - Header value
|
|
285
|
+
*/
|
|
286
|
+
setHeader(key, value) {
|
|
287
|
+
if (value) {
|
|
288
|
+
this.axios.defaults.headers.common[key] = value;
|
|
289
|
+
} else {
|
|
290
|
+
delete this.axios.defaults.headers.common[key];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Retry a request with exponential backoff
|
|
296
|
+
* @param {Function} requestFn - The request function to retry
|
|
297
|
+
* @param {number} attempt - Current attempt number
|
|
298
|
+
* @returns {Promise<Object>} Response
|
|
299
|
+
*/
|
|
300
|
+
async retryRequest(requestFn, attempt = 1) {
|
|
301
|
+
try {
|
|
302
|
+
return await requestFn();
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (attempt < this.config.retries && this.shouldRetry(error)) {
|
|
305
|
+
const delay = this.calculateBackoff(attempt);
|
|
306
|
+
|
|
307
|
+
logger.warn(`Request failed, retrying... (${attempt}/${this.config.retries})`, {
|
|
308
|
+
error: error.message,
|
|
309
|
+
retryAfterMs: delay,
|
|
310
|
+
attempt: attempt
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
await this.delay(delay);
|
|
314
|
+
return this.retryRequest(requestFn, attempt + 1);
|
|
315
|
+
}
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Calculate exponential backoff delay with jitter
|
|
322
|
+
* Formula: min(maxDelay, baseDelay * (2 ^ attempt)) + random jitter
|
|
323
|
+
* @param {number} attempt - Current retry attempt (1-indexed)
|
|
324
|
+
* @returns {number} Delay in milliseconds
|
|
325
|
+
*/
|
|
326
|
+
calculateBackoff(attempt) {
|
|
327
|
+
const baseDelay = this.config.retryDelay || DEFAULT_RETRY_DELAY;
|
|
328
|
+
const maxDelay = this.config.maxRetryDelay || MAX_RETRY_DELAY;
|
|
329
|
+
const jitterFactor = this.config.retryJitter !== undefined ? this.config.retryJitter : RETRY_JITTER_FACTOR;
|
|
330
|
+
|
|
331
|
+
// Exponential backoff: baseDelay * (BACKOFF_MULTIPLIER ^ (attempt - 1))
|
|
332
|
+
// attempt 1: 1000 * 1 = 1000ms
|
|
333
|
+
// attempt 2: 1000 * 2 = 2000ms
|
|
334
|
+
// attempt 3: 1000 * 4 = 4000ms
|
|
335
|
+
const exponentialDelay = baseDelay * Math.pow(BACKOFF_MULTIPLIER, attempt - 1);
|
|
336
|
+
|
|
337
|
+
// Cap at maxDelay
|
|
338
|
+
const cappedDelay = Math.min(exponentialDelay, maxDelay);
|
|
339
|
+
|
|
340
|
+
// Add random jitter to prevent thundering herd
|
|
341
|
+
// jitter range: -jitterFactor to +jitterFactor
|
|
342
|
+
const jitter = cappedDelay * jitterFactor * (2 * Math.random() - 1);
|
|
343
|
+
const finalDelay = Math.max(0, Math.round(cappedDelay + jitter));
|
|
344
|
+
|
|
345
|
+
logger.debug('Backoff calculated', {
|
|
346
|
+
attempt,
|
|
347
|
+
baseDelay,
|
|
348
|
+
exponentialDelay,
|
|
349
|
+
cappedDelay,
|
|
350
|
+
jitter: Math.round(jitter),
|
|
351
|
+
finalDelay
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
return finalDelay;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Determine if request should be retried
|
|
359
|
+
* @param {Error} error - The error object
|
|
360
|
+
* @returns {boolean} True if should retry
|
|
361
|
+
*/
|
|
362
|
+
shouldRetry(error) {
|
|
363
|
+
// Don't retry 4xx client errors (except 429 Too Many Requests and 408 Timeout)
|
|
364
|
+
if (error.response) {
|
|
365
|
+
const status = error.response.status;
|
|
366
|
+
|
|
367
|
+
// Retry server errors (5xx)
|
|
368
|
+
if (status >= HTTP_SERVER_ERROR_THRESHOLD) {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Retry specific 4xx errors
|
|
373
|
+
if (status === HTTP_TOO_MANY_REQUESTS || status === HTTP_REQUEST_TIMEOUT) {
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Don't retry other 4xx errors
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Retry network errors (no response)
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Delay for specified milliseconds
|
|
387
|
+
* @param {number} ms - Milliseconds to delay
|
|
388
|
+
* @returns {Promise<void>}
|
|
389
|
+
*/
|
|
390
|
+
delay(ms) {
|
|
391
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Handle error responses
|
|
396
|
+
* @param {Error} error - The error object
|
|
397
|
+
* @param {string} method - HTTP method
|
|
398
|
+
* @param {string} url - Request URL
|
|
399
|
+
* @returns {Object} Error response
|
|
400
|
+
*/
|
|
401
|
+
handleError(error, method, url) {
|
|
402
|
+
const errorInfo = {
|
|
403
|
+
method,
|
|
404
|
+
url,
|
|
405
|
+
message: error.message,
|
|
406
|
+
status: error.response?.status || 500,
|
|
407
|
+
data: error.response?.data || null
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
logger.error(`HTTP ${method} failed: ${url}`, errorInfo);
|
|
411
|
+
|
|
412
|
+
// Re-throw error with preserved response data for upstream handlers
|
|
413
|
+
const enhancedError = new Error(error.message);
|
|
414
|
+
enhancedError.response = error.response; // Preserve full response for detailed error handling
|
|
415
|
+
enhancedError.status = errorInfo.status;
|
|
416
|
+
enhancedError.data = errorInfo.data;
|
|
417
|
+
|
|
418
|
+
throw enhancedError;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Test connection to server
|
|
423
|
+
* @returns {Promise<Object>} Connection test result
|
|
424
|
+
*/
|
|
425
|
+
async testConnection() {
|
|
426
|
+
try {
|
|
427
|
+
const response = await this.axios.get('/');
|
|
428
|
+
return {
|
|
429
|
+
success: true,
|
|
430
|
+
message: 'Connection successful',
|
|
431
|
+
status: response.status
|
|
432
|
+
};
|
|
433
|
+
} catch (error) {
|
|
434
|
+
return {
|
|
435
|
+
success: false,
|
|
436
|
+
message: `Connection failed: ${error.message}`,
|
|
437
|
+
status: error.response?.status || 500
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Get HTTP client statistics
|
|
444
|
+
* @returns {Object} Client stats
|
|
445
|
+
*/
|
|
446
|
+
getStats() {
|
|
447
|
+
return {
|
|
448
|
+
baseUrl: this.config.baseUrl,
|
|
449
|
+
timeout: this.config.timeout,
|
|
450
|
+
retries: this.config.retries,
|
|
451
|
+
retryDelay: this.config.retryDelay,
|
|
452
|
+
keepAlive: this.config.keepAlive,
|
|
453
|
+
maxSockets: this.config.maxSockets,
|
|
454
|
+
maxFreeSockets: this.config.maxFreeSockets
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Cleanup and destroy HTTP agents
|
|
460
|
+
* Closes all open connections in the pool
|
|
461
|
+
*/
|
|
462
|
+
destroy() {
|
|
463
|
+
logger.debug('Destroying HTTP client and closing connection pools');
|
|
464
|
+
|
|
465
|
+
if (this.httpAgent) {
|
|
466
|
+
this.httpAgent.destroy();
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (this.httpsAgent) {
|
|
470
|
+
this.httpsAgent.destroy();
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
module.exports = HttpClient;
|