Created
March 12, 2025 09:54
base configs for axios
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Axios, { AxiosProgressEvent } from "axios"; | |
import nProgress from "nprogress"; | |
import { Store } from "vuex"; | |
import { Router } from "vue-router/auto"; | |
import { version } from "../../package.json"; | |
const globalCancelToken = Axios.CancelToken.source(); | |
// progress bar on top of the page on every axios request. | |
// heavily inspired by https://github.com/rikmms/progress-bar-4-axios | |
nProgress.configure({ | |
showSpinner: false, | |
minimum: 0.2, | |
template: "<div class='nprogress-bar' role='bar'></div>", | |
}); | |
const update = ({ progress }: AxiosProgressEvent) => { | |
if ((progress ?? 1) * 100 < 100) { | |
nProgress.inc(progress); | |
} | |
}; | |
export class RequestError extends Error { | |
reason: string; | |
status: number; | |
errors: string[]; | |
constructor(reason: string, status: number, errors: string[]) { | |
super(); | |
this.reason = reason; | |
this.status = status; | |
this.errors = errors; | |
} | |
} | |
const axios = Axios.create({ | |
baseURL: BASE_URL, | |
headers: { "Content-Type": "application/json", "X-Version": version }, | |
// loading indicator | |
onUploadProgress: update, | |
onDownloadProgress: update, | |
}); | |
export const setupAxiosInterceptors = ($store: Store<StoreState>, $router: Router) => { | |
const goToErrorPage = async (page: string) => { | |
await $router.replace(page); | |
return | |
}; | |
// request | |
axios.interceptors.request.use((req) => { | |
req.headers["X-Version"] = version; | |
// attach token to requests | |
req.headers.Authorization = `Bearer ${<auth token>}`; | |
return req; | |
}); | |
// response | |
axios.interceptors.response.use( | |
({ data }) => { | |
nProgress.done(); | |
let result = data; | |
if (!result) { | |
return result; | |
} | |
if (Object.prototype.hasOwnProperty.call(data, "msg")) { | |
result = data.msg; | |
} else if ( | |
Object.prototype.hasOwnProperty.call(data, "message") && | |
Object.keys(data).length === 1 | |
) { | |
result = data.message; | |
} | |
return result; | |
}, | |
async (error) => { | |
nProgress.done(); | |
// request cancelled because of maintenance. do nothing | |
if (Axios.isCancel(error) || isHealthCheckRequest) { | |
return; | |
} | |
// there was an error connecting to the api | |
if (error.toJSON) { | |
const msg = error.toJSON().message.toLowerCase(); | |
if (msg.includes("network error") || msg.includes("empty response")) { | |
console.log("couldn't reach server"); | |
} else if (msg.includes("aborted")) { | |
console.log("request aborted"); | |
} | |
return; | |
} | |
if (import.meta.env.VITE_NODE_ENV === "local") { | |
console.log(error, error.response); | |
} | |
// un unexpected error occurred | |
if (!error.response) { | |
return Promise.reject(error); | |
} | |
const { data, status } = error.response; | |
let errorMsg = data; | |
if (Object.prototype.hasOwnProperty.call(data, "error")) { | |
errorMsg = data.error; | |
} else if (Object.prototype.hasOwnProperty.call(data, "reason")) { | |
errorMsg = data.reason; | |
} | |
throw new RequestError(errorMsg, status, data.errors); | |
}, | |
); | |
}; | |
export default axios; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment