UNPKG

@ribajs/core

Version:

Core module of Riba.js

232 lines (214 loc) 6.74 kB
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; }[] = []; }