ff-admin-webapi-client/src/http.ts

82 lines
2.2 KiB
TypeScript

import axios, { AxiosInstance } from "axios";
import { BaseClient } from "./clients/clientBase";
import { EventEmitterReadonly, TypedEventEmitter } from "./utils/typedEmitter";
type HttpEvents = {
info: [arg1: string];
error: [arg1: { code: string; message: string }];
};
export default class HTTP {
public readonly http: AxiosInstance;
protected readonly httpEmitter: TypedEventEmitter<HttpEvents>;
protected client: BaseClient;
constructor(client: BaseClient) {
this.client = client;
this.http = axios.create({
baseURL: this.client.serverAdress + "/api",
headers: {
"Cache-Control": "no-cache",
Pragma: "no-cache",
Expires: "0",
},
});
this.httpEmitter = new TypedEventEmitter<HttpEvents>();
this.setRequestInterceptor();
this.setResponseInterceptor();
}
get httpEvents(): EventEmitterReadonly<HttpEvents> {
return this.httpEmitter;
}
private setRequestInterceptor() {
this.http.interceptors.request.use(
(config) => {
if (config.headers && !config.headers.Authorization) {
config.headers.Authorization = `Bearer ${this.client.accessToken}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
}
private setResponseInterceptor() {
this.http.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
if (!error.config.url.includes("/admin")) {
return Promise.reject(error);
}
const originalRequest = error.config;
// Handle token expiration and retry the request with a refreshed token
if (error.response && error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
return await this.client
.refreshToken()
.then(() => {
this.httpEmitter.emit("info", "successfully refreshed token");
return this.http(originalRequest);
})
.catch(() => {});
}
this.httpEmitter.emit("error", {
code: error.code,
message: error.message,
});
return Promise.reject(error);
}
);
}
}