Skip to content

Instantly share code, notes, and snippets.

@prasathmani
Last active June 13, 2024 10:57
Show Gist options
  • Save prasathmani/849a61014c0d8590eb3351e59b0b721e to your computer and use it in GitHub Desktop.
Save prasathmani/849a61014c0d8590eb3351e59b0b721e to your computer and use it in GitHub Desktop.
Axios HTTP Client Using TypeScript | Axios Wrapper TypeScript
/**
* http.ts
* author by @ccpprogrammers
*/
import axios, {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios';
enum StatusCode {
Unauthorized = 401,
Forbidden = 403,
TooManyRequests = 429,
InternalServerError = 500,
}
const headers: Readonly<Record<string, string | boolean>> = {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
'Access-Control-Allow-Credentials': true,
'X-Requested-With': 'XMLHttpRequest',
};
// We can use the following function to inject the JWT token through an interceptor
// We get the `accessToken` from the localStorage that we set when we authenticate
const injectToken = (
config: InternalAxiosRequestConfig
): InternalAxiosRequestConfig => {
try {
const token = localStorage.getItem('accessToken');
if (token != null && config?.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
} catch (error: unknown) {
const { message } = error as Error;
throw new Error(message);
}
};
class Http {
private instance: AxiosInstance | null = null;
private get http(): AxiosInstance {
return this.instance != null ? this.instance : this.initHttp();
}
initHttp() {
const http = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000',
timeout: 20000,
headers,
withCredentials: true,
});
http.interceptors.request.use(injectToken, error => Promise.reject(error));
http.interceptors.response.use(
response => response,
error => {
const { response } = error;
return this.handleError(response);
}
);
this.instance = http;
return http;
}
request<T = any, R = AxiosResponse<T>>(
config: AxiosRequestConfig
): Promise<R> {
return this.http.request(config);
}
get<T = any, R = AxiosResponse<T>>(
url: string,
config?: AxiosRequestConfig
): Promise<R> {
return this.http.get<T, R>(url, config);
}
post<T = any, R = AxiosResponse<T>>(
url: string,
data?: T,
config?: AxiosRequestConfig
): Promise<R> {
return this.http.post<T, R>(url, data, config);
}
put<T = any, R = AxiosResponse<T>>(
url: string,
data?: T,
config?: AxiosRequestConfig
): Promise<R> {
return this.http.put<T, R>(url, data, config);
}
delete<T = any, R = AxiosResponse<T>>(
url: string,
config?: AxiosRequestConfig
): Promise<R> {
return this.http.delete<T, R>(url, config);
}
// Handle global app errors
// We can handle generic app errors depending on the status code
private handleError(error: any) {
const { status } = error;
switch (status) {
case StatusCode.InternalServerError: {
// Handle InternalServerError
break;
}
case StatusCode.Forbidden: {
// Handle Forbidden
break;
}
case StatusCode.Unauthorized: {
// Handle Unauthorized
break;
}
case StatusCode.TooManyRequests: {
// Handle TooManyRequests
break;
}
}
return Promise.reject(error);
}
}
export const http = new Http();
@prasathmani
Copy link
Author

Usage

// users.service.ts
import { http } from "./http";

export type User = {
  id: string;
  name: string;
  avatar: string;
  email: string;
};

export const fetchUsers = async (): Promise<User[]> => {
  return await http.get<User[]>("/users");
};

export const createUser = async (user: User): Promise<User> => {
  return await http.post<User>("/users", user);
};

export const updateUser = async (user: User): Promise<User> => {
  return await http.put<User>(`/users/${user.id}`, user);
};

export const deleteUser = async (user: User): Promise<User> => {
  return await http.delete<User>(`/users/${user.id}`);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment