UNPKG

@intuitionrobotics/thunderstorm

Version:
276 lines 8.64 kB
import { _keys, _setTimeout, BadImplementationException } from "@intuitionrobotics/ts-common"; import { HttpMethod } from "./types.js"; import { HttpException } from "./request-types.js"; export class BaseHttpRequest { key; requestData; errorMessage; successMessage; origin; headers = {}; method = HttpMethod.GET; timeout = 10000; body; url; params; responseType; defaultHeaders = {}; label; onProgressListener; handleRequestSuccess; handleRequestFailure; onError; aborted = false; compress; defaultResponseHandler; constructor(requestKey, requestData) { this.key = requestKey; this.requestData = requestData; this.compress = false; } setHandleRequestSuccess(handleRequestSuccess) { this.handleRequestSuccess = handleRequestSuccess; return this; } setHandleRequestFailure(handleRequestFailure) { this.handleRequestFailure = handleRequestFailure; return this; } getErrorMessage() { return this.errorMessage; } getSuccessMessage() { return this.successMessage; } getRequestData() { return this.requestData; } setOrigin(origin) { this.origin = origin; return this; } setOnError(errorMessage) { if (typeof errorMessage === "string") { // noinspection JSConstantReassignment this.errorMessage = errorMessage; } else this.onError = errorMessage; return this; } setOnSuccessMessage(successMessage) { // noinspection JSConstantReassignment this.successMessage = successMessage; return this; } setOnProgressListener(onProgressListener) { this.onProgressListener = onProgressListener; return this; } setDefaultRequestHandler(processDefaultResponseHandlers) { this.defaultResponseHandler = processDefaultResponseHandlers; return this; } setLabel(label) { this.label = label; return this; } setMethod(method) { this.method = method; return this; } setResponseType(responseType) { this.responseType = responseType; return this; } setUrlParams(params) { if (!params) return this; _keys(params).forEach((key) => { const param = params[key]; return param && typeof param === "string" && this.setUrlParam(key, param); }); return this; } setUrlParam(key, value) { if (!this.params) this.params = {}; else delete this.params[key]; this.params[key] = value; return this; } setUrl(url) { this.url = url; return this; } setRelativeUrl(relativeUrl) { this.url = this.origin + relativeUrl; return this; } setTimeout(timeout) { this.timeout = timeout; return this; } setHeaders(headers) { if (!headers) return this; Object.keys(headers).forEach((key) => this.setHeader(key, headers[key])); return this; } setDefaultHeaders(headers) { this.defaultHeaders = headers; return this; } addHeaders(headers) { if (!headers) return this; Object.keys(headers).forEach((key) => this.addHeader(key, headers[key])); return this; } setHeader(_key, value) { const key = _key.toLowerCase(); delete this.headers[key]; return this.addHeader(key, value); } addHeader(_key, value) { const key = _key.toLowerCase(); return this._addHeaderImpl(key, value); } removeHeader(key) { delete this.headers[key]; return this; } _addHeaderImpl(key, value) { const values = Array.isArray(value) ? value : [value]; if (!this.headers[key]) this.headers[key] = values; else this.headers[key].push(...values); return this; } setJsonBody(bodyObject, compress) { this.setHeader("content-type", "application/json"); this.setBody(this.prepareJsonBody(bodyObject), compress); return this; } prepareJsonBody(bodyObject) { return bodyObject; } setBody(bodyAsString, _compress) { this.body = bodyAsString; this.compress = _compress === undefined ? this.compress : _compress; if (typeof bodyAsString === "string" && this.compress) this.setHeader("Content-encoding", "gzip"); return this; } asJson() { const response = this.getResponse(); if (!response) throw new BadImplementationException("No xhr.response..."); return JSON.parse(response); } asText() { const response = this.getResponse(); if (!response) throw new BadImplementationException("No xhr object... maybe you didn't wait for the request to return??"); return response; } resolveResponse() { const rawResponse = this.getResponse(); let response = undefined; if (rawResponse) { try { response = rawResponse && this.asJson(); } catch (_e) { response = this.asText(); } } return response; } handleFailure(reject) { const errorResponse = this.getErrorResponse(); this.onError?.(this, errorResponse); this.handleRequestFailure(this, errorResponse); reject?.(errorResponse); } isValidStatus() { const statusCode = this.getStatus(); return statusCode >= 200 && statusCode < 300; } async executeSync() { this.addDefaultHeaders(); try { await this.executeImpl(); } catch (e) { this.handleFailure(); throw new HttpException(this.getStatus(), this.url, e); } if (this.aborted) throw new HttpException(this.getStatus(), this.url); // should be status 0 // run this anyway to have consistent behaviour this.defaultResponseHandler?.(this); if (!this.isValidStatus()) { this.handleFailure(); throw new HttpException(this.getStatus(), this.url); } this.handleRequestSuccess(this); return this.resolveResponse(); } execute(responseHandler) { this.addDefaultHeaders(); const toCall = async (resolve, reject) => { await this.executeImpl(); if (this.aborted) return resolve(); if (this.defaultResponseHandler?.(this)) return resolve(); if (!this.isValidStatus()) return this.handleFailure(reject); const response = this.resolveResponse(); if (responseHandler) await responseHandler(response, this.requestData); this.handleRequestSuccess(this); resolve(); }; _setTimeout(() => { const label = this.label || `http request: ${this.key}`; new Promise(toCall) .then(() => console.log(`Async call completed: ${label}`)) .catch(reason => console.warn(`Async call error: ${label}`, reason)); }); return this; } getUrl = () => this.url; abort() { this.aborted = true; this.abortImpl(); } addDefaultHeaders = () => { Object.keys(this.defaultHeaders).forEach((_key) => { // If the header has been set during the call I don't add the defaults. i.e. override if (this.headers[_key]) return; const defaultHeader = this.defaultHeaders[_key]; switch (typeof defaultHeader) { case "function": this.addHeader(_key, defaultHeader(this.url)); return; case "string": this.addHeader(_key, defaultHeader); return; case "object": if (Array.isArray(defaultHeader)) { this.addHeader(_key, defaultHeader); return; } // I want this to follow through default: throw new BadImplementationException("Headers values can only be of type: (() => string | string[]) | string | string[] "); } }); }; } //# sourceMappingURL=BaseHttpRequest.js.map