| import axios from 'axios'; |
|
|
| |
| |
| const envUrlRaw = (process.env.REACT_APP_API_URL || '').trim(); |
| const envUrlNoTrailingSlash = envUrlRaw.replace(/\/$/, ''); |
| |
| const envBaseWithoutApi = envUrlNoTrailingSlash.replace(/\/api$/, ''); |
| const resolvedBaseURL = envBaseWithoutApi || 'https://linguabot-transhub-backend.hf.space'; |
|
|
| const api = axios.create({ |
| baseURL: resolvedBaseURL, |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| timeout: 10000, |
| }); |
|
|
| |
| console.log('π§ API CONFIGURATION DEBUG'); |
| console.log('Environment variables:', { |
| REACT_APP_API_URL: process.env.REACT_APP_API_URL, |
| NODE_ENV: process.env.NODE_ENV |
| }); |
| console.log('Resolved API Base URL:', resolvedBaseURL); |
| console.log('Build timestamp:', new Date().toISOString()); |
|
|
| |
| api.interceptors.request.use( |
| (config) => { |
| const token = localStorage.getItem('token'); |
| if (token) { |
| config.headers.Authorization = `Bearer ${token}`; |
| } |
| |
| |
| const user = localStorage.getItem('user'); |
| const viewMode = (localStorage.getItem('viewMode') || 'auto'); |
| if (user) { |
| try { |
| const userData = JSON.parse(user); |
| |
| const effectiveRole = viewMode === 'student' ? 'student' : (userData.role || 'visitor'); |
| config.headers['user-role'] = effectiveRole; |
| const derivedUsername = userData.username || userData.name || userData.displayName || (userData.email ? String(userData.email).split('@')[0] : undefined); |
| config.headers['user-info'] = JSON.stringify({ |
| _id: userData._id || userData.id, |
| username: derivedUsername, |
| name: userData.name, |
| displayName: userData.displayName, |
| email: userData.email, |
| role: userData.role |
| }); |
| } catch (error) { |
| config.headers['user-role'] = 'visitor'; |
| } |
| } |
| |
| |
| console.log('π Making API request to:', (config.baseURL || '') + (config.url || '')); |
| console.log('π Auth token:', token ? 'Present' : 'Missing'); |
| |
| return config; |
| }, |
| (error) => { |
| return Promise.reject(error); |
| } |
| ); |
|
|
| |
| api.interceptors.response.use( |
| (response) => { |
| console.log('β
API response received:', response.config.url); |
| return response; |
| }, |
| (error) => { |
| console.error('β API request failed:', error.config?.url, error.message); |
| |
| |
| if (error.response?.status === 401 && !error.config?.url?.includes('/subtitles/update/')) { |
| |
| localStorage.removeItem('token'); |
| localStorage.removeItem('user'); |
| window.location.href = '/login'; |
| } else if (error.response?.status === 429) { |
| |
| console.warn('Rate limit exceeded, retrying after delay...'); |
| return new Promise(resolve => { |
| setTimeout(() => { |
| resolve(api.request(error.config)); |
| }, 2000); |
| }); |
| } else if (error.response?.status === 503) { |
| |
| const cfg: any = error.config || {}; |
| cfg.__retryCount = cfg.__retryCount || 0; |
| if (cfg.__retryCount < 2) { |
| cfg.__retryCount += 1; |
| const delay = 500 * Math.pow(2, cfg.__retryCount); |
| return new Promise(resolve => setTimeout(() => resolve(api.request(cfg)), delay)); |
| } |
| } else if (error.response?.status === 500) { |
| console.error('Server error:', error.response.data); |
| } else if (error.code === 'ECONNABORTED') { |
| console.error('Request timeout'); |
| } |
| return Promise.reject(error); |
| } |
| ); |
|
|
| export { api }; |