@intuitionrobotics/thunderstorm
Version:
276 lines • 8.64 kB
JavaScript
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