This repository has been archived on 2026-07-21. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cloud-reader/frontend/src/api/client.ts
T
crisleo94 6b4c0c43f8 feat: uv config other feats
- add uv configuration for the backend
- update frontend to make auth work
- add new auth endpoints
- add bookmars feat
- add reader feat
2026-06-03 22:06:01 -05:00

67 lines
1.8 KiB
TypeScript

import axios from "axios";
const api = axios.create({
baseURL: "/api",
headers: {
"Content-Type": "application/json",
},
});
// Attach JWT token to every request
api.interceptors.request.use((config) => {
const token = localStorage.getItem("access_token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Attempt token refresh on 401
let isRefreshing = false;
let pendingRequests: Array<(token: string) => void> = [];
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response?.status !== 401 || originalRequest._retry) {
return Promise.reject(error);
}
if (isRefreshing) {
return new Promise((resolve) => {
pendingRequests.push((token: string) => {
originalRequest.headers.Authorization = `Bearer ${token}`;
resolve(api(originalRequest));
});
});
}
originalRequest._retry = true;
isRefreshing = true;
try {
const refreshToken = localStorage.getItem("refresh_token");
if (!refreshToken) {
throw new Error("No refresh token");
}
const { data } = await axios.post("/api/auth/token/refresh/", {
refresh: refreshToken,
});
localStorage.setItem("access_token", data.access);
pendingRequests.forEach((cb) => cb(data.access));
pendingRequests = [];
originalRequest.headers.Authorization = `Bearer ${data.access}`;
return api(originalRequest);
} catch {
localStorage.removeItem("access_token");
localStorage.removeItem("refresh_token");
window.location.href = "/auth";
return Promise.reject(error);
} finally {
isRefreshing = false;
}
}
);
export default api;