@ribajs/core
Version:
Core module of Riba.js
232 lines (214 loc) • 6.74 kB
text/typescript
import { extend, isJson } from "@ribajs/utils/src/type.js";
import { HttpMethod } from "../types/http-method.js";
import { HttpServiceOptions, HttpServiceResponse } from "../types/index.js";
export class HttpService {
/**
* Set header for each request
* @param name Header name
* @param value Header value
*/
public static setRequestHeaderEachRequest(name: string, value: string) {
this._requestHeadersEachRequest.push({
name,
value,
});
}
/**
* Load JSON-encoded data from the server using a GET HTTP request.
* @param url A string containing the URL to which the request is sent.
* @param data A plain object or string that is sent to the server with the request.
* @see https://api.jquery.com/jquery.getjson/
*/
public static async getJSON<T = any>(
url: string,
data?: any,
headers: any = {},
options: HttpServiceOptions = {},
) {
return this.fetch<T>(url, "GET", data, "json", headers, options);
}
/**
* Load data from the server using a HTTP POST request.
* @param url A string containing the URL to which the request is sent.
* @param data A plain object or string that is sent to the server with the request.
* @param dataType The type of data expected from the server. Default: Intelligent Guess (xml, json, script, text, html).
* @see https://api.jquery.com/jquery.post/
*/
public static async post<T = any>(
url: string,
data?: any,
dataType?: string,
headers: any = {},
options: HttpServiceOptions = {},
) {
return this.fetch<T>(url, "POST", data, dataType, headers, options);
}
public static async delete<T = any>(
url: string,
data?: any,
dataType?: string,
headers: any = {},
options: HttpServiceOptions = {},
) {
return this.fetch<T>(url, "DELETE", data, dataType, headers, options);
}
public static async put<T = any>(
url: string,
data?: any,
dataType?: string,
headers: any = {},
options: HttpServiceOptions = {},
) {
return this.fetch<T>(url, "PUT", data, dataType, headers, options);
}
/**
* Load data from the server using a HTTP GET request.
* @param url A string containing the URL to which the request is sent.
* @param data A plain object or string that is sent to the server with the request.
* @param dataType The type of data expected from the server. Default: Intelligent Guess (xml, json, script, text, html).
* @see https://api.jquery.com/jquery.get/
*/
public static async get<T = any>(
url: string,
data?: any,
dataType?: string,
headers: any = {},
options: HttpServiceOptions = {},
) {
return this.fetch<T>(url, "GET", data, dataType, headers, options);
}
/**
*
* @param dataType The type of data expected from the server. Default: Intelligent Guess (xml, json, script, text, html).
*/
public static parseDataType(dataType: string) {
const headers: { "Content-Type"?: string; Accept?: string } = {};
let contentType = "application/x-www-form-urlencoded";
let accept = "*/*";
switch (dataType) {
case "script":
contentType = "application/javascript";
break;
case "json":
contentType = "application/json";
accept = "application/json, text/javascript";
break;
case "xml":
contentType = "application/xml";
accept = "application/xml, text/xml";
break;
case "text":
contentType = "text/plain";
accept = "text/plain";
break;
case "html":
contentType = "text/html";
accept = "text/html";
break;
case "form":
contentType = "application/x-www-form-urlencoded";
break;
// case "multi-form":
// contentType = "multipart/form-data";
// break;
}
if (contentType) {
headers["Content-Type"] = contentType;
// tslint:disable-next-line:no-string-literal
headers["Accept"] = accept;
}
return headers;
}
public static async fetch<T = any>(
url: string,
method: HttpMethod = "GET",
data: any = {},
dataType?: string,
headers: any = {},
options: HttpServiceOptions = {},
): Promise<HttpServiceResponse<T>> {
if (!fetch) {
throw new Error(
"The fetch API is required. Riba targets modern browsers with native fetch support.",
);
}
let body;
// headers
for (const header of this._requestHeadersEachRequest) {
headers[header.name] = header.value;
}
if (dataType) {
headers = extend({ deep: false }, headers, this.parseDataType(dataType));
}
if (!options.crossDomain && !headers["X-Requested-With"]) {
headers["X-Requested-With"] = "XMLHttpRequest";
}
const cache = options.cache ? options.cache : "default";
if (method === "GET" && data) {
const queryStr = new URLSearchParams(data).toString();
if (queryStr) {
const separator = url.includes("?") ? "&" : "?";
url = url + separator + new URLSearchParams(data).toString();
}
} else if (data) {
if (dataType === "form") {
body = new URLSearchParams(data);
} else {
body = JSON.stringify(data);
}
}
const response = await fetch(url, {
credentials: "same-origin",
cache,
method,
body,
headers,
mode: options.mode || "cors",
});
let bodyResult = (await response.text()) as unknown as T;
if (typeof bodyResult === "string" && isJson(bodyResult)) {
bodyResult = JSON.parse(bodyResult);
}
if (typeof bodyResult === "string") {
switch (bodyResult) {
case "null":
bodyResult = null as unknown as T;
break;
case "true":
bodyResult = true as unknown as T;
break;
case "false":
bodyResult = false as unknown as T;
break;
case "undefined":
bodyResult = undefined as unknown as T;
break;
}
}
const result: HttpServiceResponse<T> = {
status: response.status,
headers: response.headers,
ok: response.ok,
redirected: response.redirected,
statusText: response.statusText,
// trailer: response.trailer,
type: response.type,
url: response.url,
arrayBuffer: response.arrayBuffer,
blob: response.blob,
bodyUsed: response.bodyUsed,
clone: response.clone,
formData: response.formData,
text: response.text,
body: bodyResult,
};
return result;
}
/**
* Header name value pair to send on each request
*/
protected static _requestHeadersEachRequest: {
name: string;
value: string;
}[] = [];
}