UNPKG

@fnlb-project/fnbr

Version:

A library to interact with Epic Games' Fortnite HTTP and XMPP services

166 lines 7.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const Base_1 = tslib_1.__importDefault(require("../Base")); const AuthenticationMissingError_1 = tslib_1.__importDefault(require("../exceptions/AuthenticationMissingError")); const constants_1 = require("../../resources/constants"); const EpicgamesAPIError_1 = tslib_1.__importDefault(require("../exceptions/EpicgamesAPIError")); /** * Represents the client's HTTP manager * @private */ class HTTP extends Base_1.default { /** * @param client The main client */ constructor(client) { super(client); } /** * Sends an HTTP request * @param config The request config * @param retries How many times this request has been retried (5xx errors) */ async request(config, retries = 0) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; const reqStartTime = Date.now(); const { url, method = 'GET', headers = {}, data, responseType } = config; let body; const finalHeaders = { 'Accept-Language': this.client.config.language, ...this.client.config.defaultHeaders, ...headers, }; if (data) { if (headers['Content-Type'] === 'application/x-www-form-urlencoded') { body = data; finalHeaders['Content-Type'] = 'application/x-www-form-urlencoded'; } else if (headers['Content-Type'] === 'application/json' || (typeof data === 'object' && !(data instanceof ArrayBuffer))) { body = JSON.stringify(data); finalHeaders['Content-Type'] = 'application/json'; } else { body = data; } } try { const response = await ((_a = this.client.config.restFetchAdapter) !== null && _a !== void 0 ? _a : fetch)(this.client.config.restTransformURL ? this.client.config.restTransformURL(url) : url, { method, headers: finalHeaders, body, }); const reqDuration = ((Date.now() - reqStartTime) / 1000); this.client.debug(`${method.toUpperCase()} ${url} (${reqDuration.toFixed(2)}s): ` + `${response.status} ${response.statusText}`, 'http'); if (!response.ok) { let errorData = null; let responseBody = ''; try { if ((_b = response.headers.get('content-type')) === null || _b === void 0 ? void 0 : _b.includes('application/json')) { errorData = await response.json(); } else if ((_c = response.headers.get('content-type')) === null || _c === void 0 ? void 0 : _c.includes('text')) { responseBody = await response.text(); } else { responseBody = await response.text(); } } catch { } const errorMessage = `HTTP ${response.status}: ${method} ${url}: ${responseBody}`; const error = new Error(errorMessage); Object.assign(error, { response, errorData, responseBody, }); throw error; } const contentType = response.headers.get("Content-Type") || ""; if (responseType === 'arraybuffer') { return await response.arrayBuffer(); } else if (responseType === 'blob' || contentType.includes("application/octet-stream")) { return await response.blob(); } else if (responseType === 'json' || contentType.includes("application/json")) { return await response.json(); } else if (responseType === 'formdata' || contentType.includes("multipart/form-data")) { return await response.formData(); } else if (contentType.includes("image/")) { const blob = await response.blob(); return URL.createObjectURL(blob); } else if (contentType.includes("application/x-www-form-urlencoded")) { const text = await response.text(); return new URLSearchParams(text); } else { return await response.text(); } } catch (err) { const reqDuration = ((Date.now() - reqStartTime) / 1000); this.client.debug(`${method.toUpperCase()} ${url} (${reqDuration.toFixed(2)}s): ${err.name} - ${err.message}`, 'http'); if (((_e = (_d = err.response) === null || _d === void 0 ? void 0 : _d.status) === null || _e === void 0 ? void 0 : _e.toString().startsWith('5')) && retries < this.client.config.restRetryLimit) { return this.request(config, retries + 1); } if (((_f = err.response) === null || _f === void 0 ? void 0 : _f.status) === 429 || ((_g = err.errorData) === null || _g === void 0 ? void 0 : _g.errorCode) === 'errors.com.epicgames.common.throttled') { const match = (_j = (_h = err.errorData) === null || _h === void 0 ? void 0 : _h.errorMessage) === null || _j === void 0 ? void 0 : _j.match(/in (\d+) second/); const retryAfter = parseInt(((_k = err.response) === null || _k === void 0 ? void 0 : _k.headers.get('Retry-After')) || ((_m = (_l = err.errorData) === null || _l === void 0 ? void 0 : _l.messageVars) === null || _m === void 0 ? void 0 : _m[0]) || (match === null || match === void 0 ? void 0 : match[1]) || '0', 10); if (!Number.isNaN(retryAfter)) { const sleepTimeout = retryAfter * 1000 + 500; await new Promise((res) => setTimeout(res, sleepTimeout)); return this.request(config, retries); } } throw err; } } /** * Sends an HTTP request to the Fortnite API * @param config The request config * @param includeAuthentication Whether to include authentication * @throws {EpicgamesAPIError} */ async epicgamesRequest(config, auth) { var _a, _b, _c; if (auth) { const authSession = this.client.auth.sessions.get(auth); if (!authSession) throw new AuthenticationMissingError_1.default(auth); await authSession.refreshLock.wait(); } try { return await this.request({ ...config, headers: { ...config.headers, ...(auth && { Authorization: `bearer ${this.client.auth.sessions.get(auth).accessToken}`, }), }, }); } catch (err) { if (auth && constants_1.invalidTokenCodes.includes((_a = err.errorData) === null || _a === void 0 ? void 0 : _a.errorCode)) { await this.client.auth.sessions.get(auth).refresh(); return this.epicgamesRequest(config, auth); } if (typeof ((_b = err.errorData) === null || _b === void 0 ? void 0 : _b.errorCode) === 'string') { throw new EpicgamesAPIError_1.default(err.errorData, config, ((_c = err.response) === null || _c === void 0 ? void 0 : _c.status) || 500); } throw err; } } } exports.default = HTTP; //# sourceMappingURL=HTTP.js.map