1 |
|
2 | "use strict";
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | var __extends = (this && this.__extends) || (function () {
|
20 | var extendStatics = function (d, b) {
|
21 | extendStatics = Object.setPrototypeOf ||
|
22 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
23 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
24 | return extendStatics(d, b);
|
25 | };
|
26 | return function (d, b) {
|
27 | extendStatics(d, b);
|
28 | function __() { this.constructor = d; }
|
29 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
30 | };
|
31 | })();
|
32 | Object.defineProperty(exports, "__esModule", { value: true });
|
33 | exports.ExponentialBackoffPoller = exports.ApiSettings = exports.AuthorizedHttpClient = exports.parseHttpResponse = exports.HttpClient = exports.defaultRetryConfig = exports.HttpError = void 0;
|
34 | var error_1 = require("./error");
|
35 | var validator = require("./validator");
|
36 | var http = require("http");
|
37 | var https = require("https");
|
38 | var url = require("url");
|
39 | var events_1 = require("events");
|
40 | var DefaultHttpResponse = (function () {
|
41 | |
42 |
|
43 |
|
44 | function DefaultHttpResponse(resp) {
|
45 | this.status = resp.status;
|
46 | this.headers = resp.headers;
|
47 | this.text = resp.data;
|
48 | try {
|
49 | if (!resp.data) {
|
50 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, 'HTTP response missing data.');
|
51 | }
|
52 | this.parsedData = JSON.parse(resp.data);
|
53 | }
|
54 | catch (err) {
|
55 | this.parsedData = undefined;
|
56 | this.parseError = err;
|
57 | }
|
58 | this.request = resp.config.method + " " + resp.config.url;
|
59 | }
|
60 | Object.defineProperty(DefaultHttpResponse.prototype, "data", {
|
61 | get: function () {
|
62 | if (this.isJson()) {
|
63 | return this.parsedData;
|
64 | }
|
65 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.UNABLE_TO_PARSE_RESPONSE, "Error while parsing response data: \"" + this.parseError.toString() + "\". Raw server " +
|
66 | ("response: \"" + this.text + "\". Status code: \"" + this.status + "\". Outgoing ") +
|
67 | ("request: \"" + this.request + ".\""));
|
68 | },
|
69 | enumerable: false,
|
70 | configurable: true
|
71 | });
|
72 | DefaultHttpResponse.prototype.isJson = function () {
|
73 | return typeof this.parsedData !== 'undefined';
|
74 | };
|
75 | return DefaultHttpResponse;
|
76 | }());
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | var MultipartHttpResponse = (function () {
|
82 | function MultipartHttpResponse(resp) {
|
83 | this.status = resp.status;
|
84 | this.headers = resp.headers;
|
85 | this.multipart = resp.multipart;
|
86 | }
|
87 | Object.defineProperty(MultipartHttpResponse.prototype, "text", {
|
88 | get: function () {
|
89 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.UNABLE_TO_PARSE_RESPONSE, 'Unable to parse multipart payload as text');
|
90 | },
|
91 | enumerable: false,
|
92 | configurable: true
|
93 | });
|
94 | Object.defineProperty(MultipartHttpResponse.prototype, "data", {
|
95 | get: function () {
|
96 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.UNABLE_TO_PARSE_RESPONSE, 'Unable to parse multipart payload as JSON');
|
97 | },
|
98 | enumerable: false,
|
99 | configurable: true
|
100 | });
|
101 | MultipartHttpResponse.prototype.isJson = function () {
|
102 | return false;
|
103 | };
|
104 | return MultipartHttpResponse;
|
105 | }());
|
106 | var HttpError = (function (_super) {
|
107 | __extends(HttpError, _super);
|
108 | function HttpError(response) {
|
109 | var _this = _super.call(this, "Server responded with status " + response.status + ".") || this;
|
110 | _this.response = response;
|
111 |
|
112 |
|
113 | Object.setPrototypeOf(_this, HttpError.prototype);
|
114 | return _this;
|
115 | }
|
116 | return HttpError;
|
117 | }(Error));
|
118 | exports.HttpError = HttpError;
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | function defaultRetryConfig() {
|
125 | return {
|
126 | maxRetries: 4,
|
127 | statusCodes: [503],
|
128 | ioErrorCodes: ['ECONNRESET', 'ETIMEDOUT'],
|
129 | backOffFactor: 0.5,
|
130 | maxDelayInMillis: 60 * 1000,
|
131 | };
|
132 | }
|
133 | exports.defaultRetryConfig = defaultRetryConfig;
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 | function validateRetryConfig(retry) {
|
140 | if (!validator.isNumber(retry.maxRetries) || retry.maxRetries < 0) {
|
141 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_ARGUMENT, 'maxRetries must be a non-negative integer');
|
142 | }
|
143 | if (typeof retry.backOffFactor !== 'undefined') {
|
144 | if (!validator.isNumber(retry.backOffFactor) || retry.backOffFactor < 0) {
|
145 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_ARGUMENT, 'backOffFactor must be a non-negative number');
|
146 | }
|
147 | }
|
148 | if (!validator.isNumber(retry.maxDelayInMillis) || retry.maxDelayInMillis < 0) {
|
149 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_ARGUMENT, 'maxDelayInMillis must be a non-negative integer');
|
150 | }
|
151 | if (typeof retry.statusCodes !== 'undefined' && !validator.isArray(retry.statusCodes)) {
|
152 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_ARGUMENT, 'statusCodes must be an array');
|
153 | }
|
154 | if (typeof retry.ioErrorCodes !== 'undefined' && !validator.isArray(retry.ioErrorCodes)) {
|
155 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_ARGUMENT, 'ioErrorCodes must be an array');
|
156 | }
|
157 | }
|
158 | var HttpClient = (function () {
|
159 | function HttpClient(retry) {
|
160 | if (retry === void 0) { retry = defaultRetryConfig(); }
|
161 | this.retry = retry;
|
162 | if (this.retry) {
|
163 | validateRetryConfig(this.retry);
|
164 | }
|
165 | }
|
166 | |
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 | HttpClient.prototype.send = function (config) {
|
181 | return this.sendWithRetry(config);
|
182 | };
|
183 | |
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 | HttpClient.prototype.sendWithRetry = function (config, retryAttempts) {
|
192 | var _this = this;
|
193 | if (retryAttempts === void 0) { retryAttempts = 0; }
|
194 | return AsyncHttpCall.invoke(config)
|
195 | .then(function (resp) {
|
196 | return _this.createHttpResponse(resp);
|
197 | })
|
198 | .catch(function (err) {
|
199 | var _a = _this.getRetryDelayMillis(retryAttempts, err), delayMillis = _a[0], canRetry = _a[1];
|
200 | if (canRetry && _this.retry && delayMillis <= _this.retry.maxDelayInMillis) {
|
201 | return _this.waitForRetry(delayMillis).then(function () {
|
202 | return _this.sendWithRetry(config, retryAttempts + 1);
|
203 | });
|
204 | }
|
205 | if (err.response) {
|
206 | throw new HttpError(_this.createHttpResponse(err.response));
|
207 | }
|
208 | if (err.code === 'ETIMEDOUT') {
|
209 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.NETWORK_TIMEOUT, "Error while making request: " + err.message + ".");
|
210 | }
|
211 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.NETWORK_ERROR, "Error while making request: " + err.message + ". Error code: " + err.code);
|
212 | });
|
213 | };
|
214 | HttpClient.prototype.createHttpResponse = function (resp) {
|
215 | if (resp.multipart) {
|
216 | return new MultipartHttpResponse(resp);
|
217 | }
|
218 | return new DefaultHttpResponse(resp);
|
219 | };
|
220 | HttpClient.prototype.waitForRetry = function (delayMillis) {
|
221 | if (delayMillis > 0) {
|
222 | return new Promise(function (resolve) {
|
223 | setTimeout(resolve, delayMillis);
|
224 | });
|
225 | }
|
226 | return Promise.resolve();
|
227 | };
|
228 | |
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 | HttpClient.prototype.getRetryDelayMillis = function (retryAttempts, err) {
|
238 | if (!this.isRetryEligible(retryAttempts, err)) {
|
239 | return [0, false];
|
240 | }
|
241 | var response = err.response;
|
242 | if (response && response.headers['retry-after']) {
|
243 | var delayMillis = this.parseRetryAfterIntoMillis(response.headers['retry-after']);
|
244 | if (delayMillis > 0) {
|
245 | return [delayMillis, true];
|
246 | }
|
247 | }
|
248 | return [this.backOffDelayMillis(retryAttempts), true];
|
249 | };
|
250 | HttpClient.prototype.isRetryEligible = function (retryAttempts, err) {
|
251 | if (!this.retry) {
|
252 | return false;
|
253 | }
|
254 | if (retryAttempts >= this.retry.maxRetries) {
|
255 | return false;
|
256 | }
|
257 | if (err.response) {
|
258 | var statusCodes = this.retry.statusCodes || [];
|
259 | return statusCodes.indexOf(err.response.status) !== -1;
|
260 | }
|
261 | if (err.code) {
|
262 | var retryCodes = this.retry.ioErrorCodes || [];
|
263 | return retryCodes.indexOf(err.code) !== -1;
|
264 | }
|
265 | return false;
|
266 | };
|
267 | |
268 |
|
269 |
|
270 |
|
271 | HttpClient.prototype.parseRetryAfterIntoMillis = function (retryAfter) {
|
272 | var delaySeconds = parseInt(retryAfter, 10);
|
273 | if (!isNaN(delaySeconds)) {
|
274 | return delaySeconds * 1000;
|
275 | }
|
276 | var date = new Date(retryAfter);
|
277 | if (!isNaN(date.getTime())) {
|
278 | return date.getTime() - Date.now();
|
279 | }
|
280 | return -1;
|
281 | };
|
282 | HttpClient.prototype.backOffDelayMillis = function (retryAttempts) {
|
283 | if (retryAttempts === 0) {
|
284 | return 0;
|
285 | }
|
286 | if (!this.retry) {
|
287 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, 'Expected this.retry to exist.');
|
288 | }
|
289 | var backOffFactor = this.retry.backOffFactor || 0;
|
290 | var delayInSeconds = (Math.pow(2, retryAttempts)) * backOffFactor;
|
291 | return Math.min(delayInSeconds * 1000, this.retry.maxDelayInMillis);
|
292 | };
|
293 | return HttpClient;
|
294 | }());
|
295 | exports.HttpClient = HttpClient;
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 | function parseHttpResponse(response, config) {
|
304 | var responseText = validator.isBuffer(response) ?
|
305 | response.toString('utf-8') : response;
|
306 | var endOfHeaderPos = responseText.indexOf('\r\n\r\n');
|
307 | var headerLines = responseText.substring(0, endOfHeaderPos).split('\r\n');
|
308 | var statusLine = headerLines[0];
|
309 | var status = statusLine.trim().split(/\s/)[1];
|
310 | var headers = {};
|
311 | headerLines.slice(1).forEach(function (line) {
|
312 | var colonPos = line.indexOf(':');
|
313 | var name = line.substring(0, colonPos).trim().toLowerCase();
|
314 | var value = line.substring(colonPos + 1).trim();
|
315 | headers[name] = value;
|
316 | });
|
317 | var data = responseText.substring(endOfHeaderPos + 4);
|
318 | if (data.endsWith('\n')) {
|
319 | data = data.slice(0, -1);
|
320 | }
|
321 | if (data.endsWith('\r')) {
|
322 | data = data.slice(0, -1);
|
323 | }
|
324 | var lowLevelResponse = {
|
325 | status: parseInt(status, 10),
|
326 | headers: headers,
|
327 | data: data,
|
328 | config: config,
|
329 | request: null,
|
330 | };
|
331 | if (!validator.isNumber(lowLevelResponse.status)) {
|
332 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, 'Malformed HTTP status line.');
|
333 | }
|
334 | return new DefaultHttpResponse(lowLevelResponse);
|
335 | }
|
336 | exports.parseHttpResponse = parseHttpResponse;
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 | var AsyncHttpCall = (function () {
|
343 | function AsyncHttpCall(config) {
|
344 | var _this = this;
|
345 | try {
|
346 | this.config = new HttpRequestConfigImpl(config);
|
347 | this.options = this.config.buildRequestOptions();
|
348 | this.entity = this.config.buildEntity(this.options.headers);
|
349 | this.promise = new Promise(function (resolve, reject) {
|
350 | _this.resolve = resolve;
|
351 | _this.reject = reject;
|
352 | _this.execute();
|
353 | });
|
354 | }
|
355 | catch (err) {
|
356 | this.promise = Promise.reject(this.enhanceError(err, null));
|
357 | }
|
358 | }
|
359 | |
360 |
|
361 |
|
362 | AsyncHttpCall.invoke = function (config) {
|
363 | return new AsyncHttpCall(config).promise;
|
364 | };
|
365 | AsyncHttpCall.prototype.execute = function () {
|
366 | var _this = this;
|
367 | var transport = this.options.protocol === 'https:' ? https : http;
|
368 | var req = transport.request(this.options, function (res) {
|
369 | _this.handleResponse(res, req);
|
370 | });
|
371 |
|
372 | req.on('error', function (err) {
|
373 | if (req.aborted) {
|
374 | return;
|
375 | }
|
376 | _this.enhanceAndReject(err, null, req);
|
377 | });
|
378 | var timeout = this.config.timeout;
|
379 | var timeoutCallback = function () {
|
380 | req.abort();
|
381 | _this.rejectWithError("timeout of " + timeout + "ms exceeded", 'ETIMEDOUT', req);
|
382 | };
|
383 | if (timeout) {
|
384 |
|
385 | req.setTimeout(timeout, timeoutCallback);
|
386 | req.on('socket', function (socket) {
|
387 | socket.setTimeout(timeout, timeoutCallback);
|
388 | });
|
389 | }
|
390 |
|
391 | req.end(this.entity);
|
392 | };
|
393 | AsyncHttpCall.prototype.handleResponse = function (res, req) {
|
394 | if (req.aborted) {
|
395 | return;
|
396 | }
|
397 | if (!res.statusCode) {
|
398 | throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, 'Expected a statusCode on the response from a ClientRequest');
|
399 | }
|
400 | var response = {
|
401 | status: res.statusCode,
|
402 | headers: res.headers,
|
403 | request: req,
|
404 | data: undefined,
|
405 | config: this.config,
|
406 | };
|
407 | var boundary = this.getMultipartBoundary(res.headers);
|
408 | var respStream = this.uncompressResponse(res);
|
409 | if (boundary) {
|
410 | this.handleMultipartResponse(response, respStream, boundary);
|
411 | }
|
412 | else {
|
413 | this.handleRegularResponse(response, respStream);
|
414 | }
|
415 | };
|
416 | |
417 |
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 | AsyncHttpCall.prototype.getMultipartBoundary = function (headers) {
|
424 | var contentType = headers['content-type'];
|
425 | if (!contentType || !contentType.startsWith('multipart/')) {
|
426 | return null;
|
427 | }
|
428 | var segments = contentType.split(';');
|
429 | var emptyObject = {};
|
430 | var headerParams = segments.slice(1)
|
431 | .map(function (segment) { return segment.trim().split('='); })
|
432 | .reduce(function (curr, params) {
|
433 |
|
434 | if (params.length === 2) {
|
435 | var keyValuePair = {};
|
436 | keyValuePair[params[0]] = params[1];
|
437 | return Object.assign(curr, keyValuePair);
|
438 | }
|
439 | return curr;
|
440 | }, emptyObject);
|
441 | return headerParams.boundary;
|
442 | };
|
443 | AsyncHttpCall.prototype.uncompressResponse = function (res) {
|
444 |
|
445 | var respStream = res;
|
446 | var encodings = ['gzip', 'compress', 'deflate'];
|
447 | if (res.headers['content-encoding'] && encodings.indexOf(res.headers['content-encoding']) !== -1) {
|
448 |
|
449 | var zlib = require('zlib');
|
450 | respStream = respStream.pipe(zlib.createUnzip());
|
451 |
|
452 | delete res.headers['content-encoding'];
|
453 | }
|
454 | return respStream;
|
455 | };
|
456 | AsyncHttpCall.prototype.handleMultipartResponse = function (response, respStream, boundary) {
|
457 | var _this = this;
|
458 | var dicer = require('dicer');
|
459 | var multipartParser = new dicer({ boundary: boundary });
|
460 | var responseBuffer = [];
|
461 | multipartParser.on('part', function (part) {
|
462 | var tempBuffers = [];
|
463 | part.on('data', function (partData) {
|
464 | tempBuffers.push(partData);
|
465 | });
|
466 | part.on('end', function () {
|
467 | responseBuffer.push(Buffer.concat(tempBuffers));
|
468 | });
|
469 | });
|
470 | multipartParser.on('finish', function () {
|
471 | response.data = undefined;
|
472 | response.multipart = responseBuffer;
|
473 | _this.finalizeResponse(response);
|
474 | });
|
475 | respStream.pipe(multipartParser);
|
476 | };
|
477 | AsyncHttpCall.prototype.handleRegularResponse = function (response, respStream) {
|
478 | var _this = this;
|
479 | var responseBuffer = [];
|
480 | respStream.on('data', function (chunk) {
|
481 | responseBuffer.push(chunk);
|
482 | });
|
483 | respStream.on('error', function (err) {
|
484 | var req = response.request;
|
485 | if (req && req.aborted) {
|
486 | return;
|
487 | }
|
488 | _this.enhanceAndReject(err, null, req);
|
489 | });
|
490 | respStream.on('end', function () {
|
491 | response.data = Buffer.concat(responseBuffer).toString();
|
492 | _this.finalizeResponse(response);
|
493 | });
|
494 | };
|
495 | |
496 |
|
497 |
|
498 |
|
499 | AsyncHttpCall.prototype.finalizeResponse = function (response) {
|
500 | if (response.status >= 200 && response.status < 300) {
|
501 | this.resolve(response);
|
502 | }
|
503 | else {
|
504 | this.rejectWithError('Request failed with status code ' + response.status, null, response.request, response);
|
505 | }
|
506 | };
|
507 | |
508 |
|
509 |
|
510 |
|
511 | AsyncHttpCall.prototype.rejectWithError = function (message, code, request, response) {
|
512 | var error = new Error(message);
|
513 | this.enhanceAndReject(error, code, request, response);
|
514 | };
|
515 | AsyncHttpCall.prototype.enhanceAndReject = function (error, code, request, response) {
|
516 | this.reject(this.enhanceError(error, code, request, response));
|
517 | };
|
518 | |
519 |
|
520 |
|
521 |
|
522 | AsyncHttpCall.prototype.enhanceError = function (error, code, request, response) {
|
523 | error.config = this.config;
|
524 | if (code) {
|
525 | error.code = code;
|
526 | }
|
527 | error.request = request;
|
528 | error.response = response;
|
529 | return error;
|
530 | };
|
531 | return AsyncHttpCall;
|
532 | }());
|
533 |
|
534 |
|
535 |
|
536 | var HttpRequestConfigImpl = (function () {
|
537 | function HttpRequestConfigImpl(config) {
|
538 | this.config = config;
|
539 | }
|
540 | Object.defineProperty(HttpRequestConfigImpl.prototype, "method", {
|
541 | get: function () {
|
542 | return this.config.method;
|
543 | },
|
544 | enumerable: false,
|
545 | configurable: true
|
546 | });
|
547 | Object.defineProperty(HttpRequestConfigImpl.prototype, "url", {
|
548 | get: function () {
|
549 | return this.config.url;
|
550 | },
|
551 | enumerable: false,
|
552 | configurable: true
|
553 | });
|
554 | Object.defineProperty(HttpRequestConfigImpl.prototype, "headers", {
|
555 | get: function () {
|
556 | return this.config.headers;
|
557 | },
|
558 | enumerable: false,
|
559 | configurable: true
|
560 | });
|
561 | Object.defineProperty(HttpRequestConfigImpl.prototype, "data", {
|
562 | get: function () {
|
563 | return this.config.data;
|
564 | },
|
565 | enumerable: false,
|
566 | configurable: true
|
567 | });
|
568 | Object.defineProperty(HttpRequestConfigImpl.prototype, "timeout", {
|
569 | get: function () {
|
570 | return this.config.timeout;
|
571 | },
|
572 | enumerable: false,
|
573 | configurable: true
|
574 | });
|
575 | Object.defineProperty(HttpRequestConfigImpl.prototype, "httpAgent", {
|
576 | get: function () {
|
577 | return this.config.httpAgent;
|
578 | },
|
579 | enumerable: false,
|
580 | configurable: true
|
581 | });
|
582 | HttpRequestConfigImpl.prototype.buildRequestOptions = function () {
|
583 | var parsed = this.buildUrl();
|
584 | var protocol = parsed.protocol;
|
585 | var port = parsed.port;
|
586 | if (!port) {
|
587 | var isHttps = protocol === 'https:';
|
588 | port = isHttps ? '443' : '80';
|
589 | }
|
590 | return {
|
591 | protocol: protocol,
|
592 | hostname: parsed.hostname,
|
593 | port: port,
|
594 | path: parsed.path,
|
595 | method: this.method,
|
596 | agent: this.httpAgent,
|
597 | headers: Object.assign({}, this.headers),
|
598 | };
|
599 | };
|
600 | HttpRequestConfigImpl.prototype.buildEntity = function (headers) {
|
601 | var data;
|
602 | if (!this.hasEntity() || !this.isEntityEnclosingRequest()) {
|
603 | return data;
|
604 | }
|
605 | if (validator.isBuffer(this.data)) {
|
606 | data = this.data;
|
607 | }
|
608 | else if (validator.isObject(this.data)) {
|
609 | data = Buffer.from(JSON.stringify(this.data), 'utf-8');
|
610 | if (typeof headers['content-type'] === 'undefined') {
|
611 | headers['content-type'] = 'application/json;charset=utf-8';
|
612 | }
|
613 | }
|
614 | else if (validator.isString(this.data)) {
|
615 | data = Buffer.from(this.data, 'utf-8');
|
616 | }
|
617 | else {
|
618 | throw new Error('Request data must be a string, a Buffer or a json serializable object');
|
619 | }
|
620 |
|
621 | headers['Content-Length'] = data.length.toString();
|
622 | return data;
|
623 | };
|
624 | HttpRequestConfigImpl.prototype.buildUrl = function () {
|
625 | var fullUrl = this.urlWithProtocol();
|
626 | if (!this.hasEntity() || this.isEntityEnclosingRequest()) {
|
627 | return url.parse(fullUrl);
|
628 | }
|
629 | if (!validator.isObject(this.data)) {
|
630 | throw new Error(this.method + " requests cannot have a body");
|
631 | }
|
632 |
|
633 | var parsedUrl = new url.URL(fullUrl);
|
634 | var dataObj = this.data;
|
635 | for (var key in dataObj) {
|
636 | if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
|
637 | parsedUrl.searchParams.append(key, dataObj[key]);
|
638 | }
|
639 | }
|
640 | return url.parse(parsedUrl.toString());
|
641 | };
|
642 | HttpRequestConfigImpl.prototype.urlWithProtocol = function () {
|
643 | var fullUrl = this.url;
|
644 | if (fullUrl.startsWith('http://') || fullUrl.startsWith('https://')) {
|
645 | return fullUrl;
|
646 | }
|
647 | return "https://" + fullUrl;
|
648 | };
|
649 | HttpRequestConfigImpl.prototype.hasEntity = function () {
|
650 | return !!this.data;
|
651 | };
|
652 | HttpRequestConfigImpl.prototype.isEntityEnclosingRequest = function () {
|
653 |
|
654 | return this.method !== 'GET' && this.method !== 'HEAD';
|
655 | };
|
656 | return HttpRequestConfigImpl;
|
657 | }());
|
658 | var AuthorizedHttpClient = (function (_super) {
|
659 | __extends(AuthorizedHttpClient, _super);
|
660 | function AuthorizedHttpClient(app) {
|
661 | var _this = _super.call(this) || this;
|
662 | _this.app = app;
|
663 | return _this;
|
664 | }
|
665 | AuthorizedHttpClient.prototype.send = function (request) {
|
666 | var _this = this;
|
667 | return this.getToken().then(function (token) {
|
668 | var requestCopy = Object.assign({}, request);
|
669 | requestCopy.headers = Object.assign({}, request.headers);
|
670 | var authHeader = 'Authorization';
|
671 | requestCopy.headers[authHeader] = "Bearer " + token;
|
672 | if (!requestCopy.httpAgent && _this.app.options.httpAgent) {
|
673 | requestCopy.httpAgent = _this.app.options.httpAgent;
|
674 | }
|
675 | return _super.prototype.send.call(_this, requestCopy);
|
676 | });
|
677 | };
|
678 | AuthorizedHttpClient.prototype.getToken = function () {
|
679 | return this.app.INTERNAL.getToken()
|
680 | .then(function (accessTokenObj) {
|
681 | return accessTokenObj.accessToken;
|
682 | });
|
683 | };
|
684 | return AuthorizedHttpClient;
|
685 | }(HttpClient));
|
686 | exports.AuthorizedHttpClient = AuthorizedHttpClient;
|
687 |
|
688 |
|
689 |
|
690 |
|
691 |
|
692 |
|
693 |
|
694 | var ApiSettings = (function () {
|
695 | function ApiSettings(endpoint, httpMethod) {
|
696 | if (httpMethod === void 0) { httpMethod = 'POST'; }
|
697 | this.endpoint = endpoint;
|
698 | this.httpMethod = httpMethod;
|
699 | this.setRequestValidator(null)
|
700 | .setResponseValidator(null);
|
701 | }
|
702 |
|
703 | ApiSettings.prototype.getEndpoint = function () {
|
704 | return this.endpoint;
|
705 | };
|
706 |
|
707 | ApiSettings.prototype.getHttpMethod = function () {
|
708 | return this.httpMethod;
|
709 | };
|
710 | |
711 |
|
712 |
|
713 |
|
714 | ApiSettings.prototype.setRequestValidator = function (requestValidator) {
|
715 | var nullFunction = function () { return undefined; };
|
716 | this.requestValidator = requestValidator || nullFunction;
|
717 | return this;
|
718 | };
|
719 |
|
720 | ApiSettings.prototype.getRequestValidator = function () {
|
721 | return this.requestValidator;
|
722 | };
|
723 | |
724 |
|
725 |
|
726 |
|
727 | ApiSettings.prototype.setResponseValidator = function (responseValidator) {
|
728 | var nullFunction = function () { return undefined; };
|
729 | this.responseValidator = responseValidator || nullFunction;
|
730 | return this;
|
731 | };
|
732 |
|
733 | ApiSettings.prototype.getResponseValidator = function () {
|
734 | return this.responseValidator;
|
735 | };
|
736 | return ApiSettings;
|
737 | }());
|
738 | exports.ApiSettings = ApiSettings;
|
739 |
|
740 |
|
741 |
|
742 |
|
743 |
|
744 |
|
745 |
|
746 |
|
747 |
|
748 |
|
749 |
|
750 |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 |
|
763 | var ExponentialBackoffPoller = (function (_super) {
|
764 | __extends(ExponentialBackoffPoller, _super);
|
765 | function ExponentialBackoffPoller(initialPollingDelayMillis, maxPollingDelayMillis, masterTimeoutMillis) {
|
766 | if (initialPollingDelayMillis === void 0) { initialPollingDelayMillis = 1000; }
|
767 | if (maxPollingDelayMillis === void 0) { maxPollingDelayMillis = 10000; }
|
768 | if (masterTimeoutMillis === void 0) { masterTimeoutMillis = 60000; }
|
769 | var _this = _super.call(this) || this;
|
770 | _this.initialPollingDelayMillis = initialPollingDelayMillis;
|
771 | _this.maxPollingDelayMillis = maxPollingDelayMillis;
|
772 | _this.masterTimeoutMillis = masterTimeoutMillis;
|
773 | _this.numTries = 0;
|
774 | _this.completed = false;
|
775 | return _this;
|
776 | }
|
777 | |
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 |
|
786 | ExponentialBackoffPoller.prototype.poll = function (callback) {
|
787 | var _this = this;
|
788 | if (this.pollCallback) {
|
789 | throw new Error('poll() can only be called once per instance of ExponentialBackoffPoller');
|
790 | }
|
791 | this.pollCallback = callback;
|
792 | this.on('poll', this.repoll);
|
793 | this.masterTimer = setTimeout(function () {
|
794 | if (_this.completed) {
|
795 | return;
|
796 | }
|
797 | _this.markCompleted();
|
798 | _this.reject(new Error('ExponentialBackoffPoller deadline exceeded - Master timeout reached'));
|
799 | }, this.masterTimeoutMillis);
|
800 | return new Promise(function (resolve, reject) {
|
801 | _this.resolve = resolve;
|
802 | _this.reject = reject;
|
803 | _this.repoll();
|
804 | });
|
805 | };
|
806 | ExponentialBackoffPoller.prototype.repoll = function () {
|
807 | var _this = this;
|
808 | this.pollCallback()
|
809 | .then(function (result) {
|
810 | if (_this.completed) {
|
811 | return;
|
812 | }
|
813 | if (!result) {
|
814 | _this.repollTimer =
|
815 | setTimeout(function () { return _this.emit('poll'); }, _this.getPollingDelayMillis());
|
816 | _this.numTries++;
|
817 | return;
|
818 | }
|
819 | _this.markCompleted();
|
820 | _this.resolve(result);
|
821 | })
|
822 | .catch(function (err) {
|
823 | if (_this.completed) {
|
824 | return;
|
825 | }
|
826 | _this.markCompleted();
|
827 | _this.reject(err);
|
828 | });
|
829 | };
|
830 | ExponentialBackoffPoller.prototype.getPollingDelayMillis = function () {
|
831 | var increasedPollingDelay = Math.pow(2, this.numTries) * this.initialPollingDelayMillis;
|
832 | return Math.min(increasedPollingDelay, this.maxPollingDelayMillis);
|
833 | };
|
834 | ExponentialBackoffPoller.prototype.markCompleted = function () {
|
835 | this.completed = true;
|
836 | if (this.masterTimer) {
|
837 | clearTimeout(this.masterTimer);
|
838 | }
|
839 | if (this.repollTimer) {
|
840 | clearTimeout(this.repollTimer);
|
841 | }
|
842 | };
|
843 | return ExponentialBackoffPoller;
|
844 | }(events_1.EventEmitter));
|
845 | exports.ExponentialBackoffPoller = ExponentialBackoffPoller;
|