Skip to content

Instantly share code, notes, and snippets.

@avishwakarma
Last active July 27, 2022 12:44
Show Gist options
  • Save avishwakarma/4c213aef03f4490297aa12ec6d0e3f67 to your computer and use it in GitHub Desktop.
Save avishwakarma/4c213aef03f4490297aa12ec6d0e3f67 to your computer and use it in GitHub Desktop.
A simple utility to make HTTP calls using XMLHttpRequest
export interface HttpResponse<T> {
data: T;
url: string;
status: number;
}
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
export type HttpHaders = { [key: string]: string };
export type QueryParams = { [key: string]: string };
export type HttpBody = Document | XMLHttpRequestBodyInit | null;
export interface HttpOptions {
params?: QueryParams;
headers?: HttpHaders;
onprogress?: (event: ProgressEvent<EventTarget>) => void;
withCredentials?: boolean;
}
class Http {
private static instance: Http;
private defaultHeaders: HttpHaders = {
"Content-Type": "application/json; charset=utf-8"
};
private constructor() {}
static getInstance(): Http {
if (!Http.instance) {
Http.instance = new Http();
}
return Http.instance;
}
private buildUrl(base: string, params?: { [key: string]: string }): string {
const url: URL = new URL(base);
if (params) {
Object.keys(params).forEach((key: string) => {
url.searchParams.set(key, params[key]);
});
}
return url.toString();
}
private send<T>(
method: HttpMethod,
url: string,
body?: HttpBody,
options?: HttpOptions
): Promise<HttpResponse<T>> {
return new Promise((resolve, reject) => {
if ((method === "POST" || method === "PUT") && !body) {
throw new Error(`Cannot make HTTP ${method} request without body.`);
}
const xhr: XMLHttpRequest = new XMLHttpRequest();
if (options?.withCredentials) {
xhr.withCredentials = true;
}
xhr.open(method, this.buildUrl(url, options && options.params));
const headers: HttpHaders = Object.assign(
this.defaultHeaders,
(options && options.headers) || {}
);
Object.keys(headers).forEach((key: string) => {
xhr.setRequestHeader(key, headers[key]);
});
xhr.send(body && body);
if (options?.onprogress) {
xhr.onprogress = options.onprogress;
}
xhr.onerror = (event: ProgressEvent<EventTarget>) => {
reject(event);
};
xhr.onreadystatechange = (event: Event) => {
// resolve promise
// do the data strtansformation as HttpResponse
resolve({ ... });
};
});
}
get<T>(url: string, options?: HttpOptions): Promise<HttpResponse<T>> {
return this.send("GET", url, null, options);
}
post<T>(
url: string,
body: HttpBody,
options?: HttpOptions
): Promise<HttpResponse<T>> {
return this.send("POST", url, body, options);
}
put<T>(
url: string,
body: HttpBody,
options?: HttpOptions
): Promise<HttpResponse<T>> {
return this.send("PUT", url, body, options);
}
delete<T>(url: string, options?: HttpOptions): Promise<HttpResponse<T>> {
return this.send("DELETE", url, null, options);
}
}
export default Http.getInstance();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment