diff --git a/frontend/src/lib/axios.ts b/frontend/src/lib/axios.ts new file mode 100644 index 0000000..dd520c4 --- /dev/null +++ b/frontend/src/lib/axios.ts @@ -0,0 +1,50 @@ +import axios from 'axios'; +import { dev } from '$app/environment'; +import { goto } from '$app/navigation'; + +if (dev) { + axios.defaults.baseURL = "http://localhost:8000/api/v1" +} else { + axios.defaults.baseURL = "/api/v1" +} + +function createTokenRefreshInterceptor() { + const interceptor = axios.interceptors.response.use( + (response) => response, + (error) => { + // Reject promise if usual error + if (error.response.status !== 401) { + return Promise.reject(error); + } + + /* + * When response code is 401, try to refresh the token. + * Eject the interceptor so it doesn't loop in case + * token refresh causes the 401 response. + * + * Must be re-attached later on or the token refresh will only happen once + */ + axios.interceptors.response.eject(interceptor); + + return axios + .post("/auth/refresh", { + refresh_token: "", + }) + .then((response) => { + // TODO: Save token + error.response.config.headers["Authorization"] = "Bearer " + response.data.access_token; + // Retry initial request with new token + return axios(error.response.config); + }) + .catch((retryError) => { + // Retry failed, clean up and reject the promise + // TODO: Remove invalid token + goto('/login?reauth') + return Promise.reject(retryError); + }) + .finally(createTokenRefreshInterceptor); // Re-attach interceptor for future requests + } + ); +} + +createTokenRefreshInterceptor();