HTTP client¶
We provide a full stack client to create HTTP requests.
Example¶
import JsonAny, { ReadonlyJsonAny } from "../hg/core/Json";
import RequestClient from "../hg/core/RequestClient";
import { HttpService } from "./HttpService";
import { isArrayOf } from "./fi/hg/core/modules/lodash";
We find it a good practice to add an extra service layer in your software which wraps the HTTP client library you use from your business logic. This way, you can change it later easily.
export class HttpService {
public static async getJson (
url : string,
headers ?: {[key: string]: string}
) : Promise<ReadonlyJsonAny | undefined> {
const response : JsonAny | undefined = await RequestClient.getJson(url, headers);
return response as ReadonlyJsonAny | undefined;
}
public static async postJson (
url : string,
data ?: ReadonlyJsonAny,
headers ?: {[key: string]: string}
) : Promise<ReadonlyJsonAny | undefined> {
const response : JsonAny | undefined = await RequestClient.postJson(url, data as JsonAny, headers);
return response as ReadonlyJsonAny | undefined;
}
}
Then you should always create a purposeful service to implement your code. Never use the HTTP client directly from your UI code, unless that UI code is intended to create a custom HTTP request.
export class ProductService {
public static async getProductList () : Promise<ProductModel[]> {
const list : ReadonlyJsonAny | undefined = await HttpService.getJson(PRODUCT_LIST_URL);
if (isArrayOf<ProductModel>(list, isProductModel)) {
return list as ProductModel[];
}
LOG.debug(`Not product list: `, list);
throw new TypeError('Could not get product list');
}
}
You should also define a file at constants/backend.ts
which defines PRODUCT_LIST_URL
. This way,
when backend changes URLs, you know can easily find where that API path is used in your code.