export interface IHttpRequest { url: string; method: string; body: T; headers: Record; metadata: Record; } export interface IUploadProgressData { loaded: number; total: number; } export interface IUploadRequest extends IHttpRequest { onProgress?(e: IUploadProgressData): void; } export interface IHttpResponse { body: T; headers: { get(key: string): string | null; has(key: string): boolean; }; status: number; statusText: string; } /** * HTTP error containing request object and response object if server has answered. */ export declare class HttpRequestError extends Error { req: IHttpRequest; res: IHttpResponse | null; constructor(req: IHttpRequest, res: IHttpResponse | null); } /** * Request interceptor. * It can modify request object before sending. */ export declare type RequestInterceptor = (req: IHttpRequest) => void; /** * HTTP error handler. * It can deal with errors and retry sending request. * If retry is called without request argument, same request object will be used. */ export declare type ErrorHandler = (req: HttpRequestError, retry: (req?: IHttpRequest) => Promise>) => Promise | null>; export default abstract class HttpClient { protected requestInterceptors: { items: RequestInterceptor[]; add(item: RequestInterceptor): void; remove(item: RequestInterceptor): void; }; protected errorHandlers: { items: ErrorHandler[]; add(item: ErrorHandler): void; remove(item: ErrorHandler): void; }; /** * Actual request sending implementation. * @param req request data object */ protected abstract sendRequest(req: IHttpRequest): Promise>; /** * Actual file uploading request implementation. * @param req request data */ protected abstract sendFile(req: IUploadRequest): Promise>; private handleError; private pipeRequest; /** * Send HTTP request. * @param url request url * @param method request method * @param body request body * @param headers request headers * @param metadata request metadata (for internal usage, doesn't provide anything meaningful for the request itself) * @returns response object * @throws {HttpRequestError} on 4xx or 5xx status code */ fetch(url: string, method: string, body?: unknown, headers?: Record, metadata?: Record): Promise>; /** * Upload file via HTTP. * @param url request url * @param data file (request body) * @param method request method * @param headers request headers * @param metadata request metadata (for internal usage, doesn't provide anything meaningful for the request itself) * @param onProgress upload progress event callback * @returns response object * @throws {HttpRequestError} on 4xx or 5xx status code */ upload(url: string, data: Blob, { onProgress, method, headers, metadata, }?: { onProgress?(e: IUploadProgressData): void; method?: string; headers?: Record; metadata?: Record; }): Promise>; /** * Add request interceptor. It can be used to modify request before sending. * You can provide Authorization header here, for example. * @param fn request interceptor * @returns this */ addRequestInterceptor(fn: RequestInterceptor): this; /** * Remove request interceptor. If there is no interceptor, function silently returns. * @param fn request interceptor * @returns this */ removeRequestInterceptor(fn: RequestInterceptor): this; /** * Add HTTP error handler. It can be used for dealing with HTTP errors and optional recovery. * You can try to use refresh/remember token and resend request here, for example. * @param fn error handler, can return new HTTP response which will be returned to client * @returns this */ addErrorHandler(fn: ErrorHandler): this; /** * Remove error handler. If there is no handler, function silently returns. * @param fn error handler * @returns this */ removeErrorHandler(fn: ErrorHandler): this; get(url: string, headers?: Record): Promise>; post(url: string, body?: unknown, headers?: Record): Promise>; put(url: string, body?: unknown, headers?: Record): Promise>; patch(url: string, body?: unknown, headers?: Record): Promise>; delete(url: string, body?: unknown, headers?: Record): Promise>; }