Spaces:
Sleeping
Sleeping
| import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from "axios"; | |
| import { toast } from "react-hot-toast"; | |
| // Use relative URL if NEXT_PUBLIC_API_URL is empty (same domain deployment) | |
| // Otherwise use the provided URL or default to localhost | |
| const API_URL = process.env.NEXT_PUBLIC_API_URL === "" | |
| ? "" // Empty string means use relative URLs (same domain) | |
| : (process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"); | |
| // Create axios instance | |
| const apiClient: AxiosInstance = axios.create({ | |
| baseURL: API_URL, | |
| timeout: 300000, // 5 minutes for long-running operations | |
| headers: { | |
| "Content-Type": "application/json", | |
| }, | |
| }); | |
| // Request interceptor | |
| apiClient.interceptors.request.use( | |
| (config: InternalAxiosRequestConfig) => { | |
| // Add auth token if available | |
| if (typeof window !== "undefined") { | |
| const authStorage = localStorage.getItem("auth-storage"); | |
| if (authStorage) { | |
| try { | |
| const auth = JSON.parse(authStorage); | |
| if (auth.state?.token) { | |
| config.headers.Authorization = `Bearer ${auth.state.token}`; | |
| } | |
| } catch (e) { | |
| // Ignore parsing errors | |
| } | |
| } | |
| } | |
| return config; | |
| }, | |
| (error) => { | |
| return Promise.reject(error); | |
| } | |
| ); | |
| // Response interceptor for error handling | |
| apiClient.interceptors.response.use( | |
| (response) => response, | |
| (error: AxiosError) => { | |
| if (error.response) { | |
| // Server responded with error status | |
| const status = error.response.status; | |
| const message = (error.response.data as any)?.detail || error.message || "An error occurred"; | |
| // Handle 401 Unauthorized - redirect to login | |
| if (status === 401) { | |
| if (typeof window !== "undefined" && !window.location.pathname.includes("/login")) { | |
| // Clear auth storage | |
| localStorage.removeItem("auth-storage"); | |
| // Redirect to login | |
| window.location.href = "/login"; | |
| } | |
| } | |
| // Don't show toast for 404s (handled in components) or 401s (handled above) | |
| if (status !== 404 && status !== 401) { | |
| toast.error(message); | |
| } | |
| } else if (error.request) { | |
| // Request made but no response | |
| toast.error("Network error. Please check your connection."); | |
| } else { | |
| // Something else happened | |
| toast.error("An unexpected error occurred"); | |
| } | |
| return Promise.reject(error); | |
| } | |
| ); | |
| export default apiClient; | |