UNPKG

agora-rest-client

Version:
153 lines (152 loc) 6.84 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RequestClient = void 0; const types_1 = require("../types"); const utils_1 = require("../utils"); const domain_1 = require("../domain/domain"); const https = require("https"); const url_1 = require("url"); const node_fetch_1 = require("node-fetch"); const querystring_1 = require("querystring"); const resolver_1 = require("../domain/resolver"); const log_1 = require("../log"); const logger = (0, log_1.getLogger)('RequestClient'); class RequestClient { constructor(config) { this.config = config; this.domainPool = new domain_1.DomainPool(config.domainArea); this.timeout = config.httpTimeout || utils_1.DEFAULT_REQ_TIMEOUT; this.keepAliveAgent = new https.Agent({ keepAlive: true, keepAliveMsecs: 3000, }); } buildHeaders(host, userAgent) { const now = new Date(); return { accept: 'application/json', date: now.toUTCString(), host, 'content-type': 'application/json', 'user-agent': userAgent, }; } request(method, uriPattern, options) { return __awaiter(this, void 0, void 0, function* () { let err, response; const abortController = new AbortController(); const timeout = options.timeout === undefined ? this.timeout : options.timeout; let aborted = false; const timer = setTimeout(() => { clearTimeout(timer); aborted = true; abortController.abort(); }, timeout); if (this.domainPool.domainNeedUpdate()) { try { const domain = yield (0, resolver_1.bestDomain)(this.domainPool.allDomains, this.domainPool.currentRegion); this.domainPool.selectDomain(domain); } catch (e) { err = utils_1.GenericError.wrapError(utils_1.ERR_NAMESPACE_LIB, types_1.ErrorTypeEnum.RequestDNSError, e); throw err; } } // start request, but don't process response yet ; [err, response] = yield (0, utils_1.retry)(this, (retryCount) => __awaiter(this, void 0, void 0, function* () { var _a; logger.debug(`http module retry attempt ${retryCount}...`); const endpoint = this.domainPool.currentUrl; logger.debug(`current endpoint: ${endpoint}`); const parsedURL = new url_1.URL(endpoint); const host = parsedURL.hostname; const userAgent = (0, utils_1.getUserAgent)(); logger.debug(`current host: ${host},userAgent: ${userAgent}`); const mixHeaders = Object.assign(this.buildHeaders(host || '', userAgent)); (_a = this.config.credential) === null || _a === void 0 ? void 0 : _a.setAuth(mixHeaders); const fetchOptions = { method, agent: this.keepAliveAgent, headers: new node_fetch_1.Headers(mixHeaders), body: options.body, signal: abortController.signal, }; let url = `${endpoint}${uriPattern}`; if (options.query && Object.keys(options.query).length > 0) { url += `?${querystring_1.default.stringify(options.query)}`; } logger.debug(`request body: ${options.body}`); const response = yield (0, node_fetch_1.default)(url, fetchOptions); logger.debug(`status:${response.status},method:${fetchOptions.method},url:${url} requestId: ${response.headers.get('x-request-id')}`); return response; }), () => aborted, { onFailAttempt: (err) => { logger.warn(`http module error: ${err.message}`); this.domainPool.nextRegion(); }, // delay for 500ms before next request delay: (retryCount) => (retryCount >= 1 ? 500 : 0), }); this._checkRequestAborted(aborted, timer); if (err) { throw err; } if (response) { let body; try { body = yield response.json(); } catch (e) { clearTimeout(timer); throw utils_1.GenericError.wrapError(utils_1.ERR_NAMESPACE_LIB, types_1.ErrorTypeEnum.RequestResponseError, e); } clearTimeout(timer); // @ts-ignore return { body, response }; } else { clearTimeout(timer); throw utils_1.GenericError.wrapMessage(utils_1.ERR_NAMESPACE_LIB, types_1.ErrorTypeEnum.RequestResponseError, 'FormatError', 'unknown response'); } }); } put(path, options) { return __awaiter(this, void 0, void 0, function* () { return this.request('PUT', path, options); }); } post(path, options) { return __awaiter(this, void 0, void 0, function* () { return this.request('POST', path, options); }); } get(path, options) { return __awaiter(this, void 0, void 0, function* () { return this.request('GET', path, options); }); } delete(path, options) { return __awaiter(this, void 0, void 0, function* () { return this.request('DELETE', path, options); }); } // ------------------- private methods ------------------- _checkRequestAborted(aborted, timer) { if (aborted) { logger.error(`request aborted`); clearTimeout(timer); throw utils_1.GenericError.wrapMessage(types_1.ERR_NAMESPACE_CLIENT, types_1.ErrorTypeEnum.RequestTimeoutError, 'TimeoutError', 'request timeout'); } } } exports.RequestClient = RequestClient;