Fix Android app connectivity issues and add detailed logging
- Add CORS headers to backend server to allow mobile app requests - Implement request timeout (10s) in capacitor-bridge.js to prevent hanging - Add comprehensive logging throughout authentication flow - Add detailed error reporting in initApp for better debugging - Log all API requests with request IDs for traceability This fixes the 'Loading Plugin Compass...' infinite loop issue caused by missing CORS headers and unhandled network timeouts.
This commit is contained in:
@@ -116,9 +116,24 @@ async function clearAuth() {
|
||||
}
|
||||
}
|
||||
|
||||
// API client with authentication
|
||||
// API client with authentication and timeout
|
||||
const REQUEST_TIMEOUT = 10000; // 10 second timeout
|
||||
|
||||
function fetchWithTimeout(url, options, timeout = REQUEST_TIMEOUT) {
|
||||
return Promise.race([
|
||||
fetch(url, options),
|
||||
new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error(`Request timeout after ${timeout}ms`)), timeout)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
async function apiClient(endpoint, options = {}) {
|
||||
const url = endpoint.startsWith('http') ? endpoint : `${BACKEND_BASE_URL}${endpoint}`;
|
||||
const requestId = Math.random().toString(36).substring(7);
|
||||
|
||||
console.log(`[API:${requestId}] Starting request to ${endpoint}`);
|
||||
console.log(`[API:${requestId}] Full URL: ${url}`);
|
||||
|
||||
const token = await getAuthToken();
|
||||
const headers = {
|
||||
@@ -128,20 +143,28 @@ async function apiClient(endpoint, options = {}) {
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
console.log(`[API:${requestId}] Sending ${options.method || 'GET'} request...`);
|
||||
const startTime = Date.now();
|
||||
|
||||
const response = await fetchWithTimeout(url, {
|
||||
...options,
|
||||
headers,
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
console.log(`[API:${requestId}] Response received in ${duration}ms - Status: ${response.status}`);
|
||||
|
||||
// Handle token expiration
|
||||
if (response.status === 401) {
|
||||
console.log(`[API:${requestId}] Token expired, attempting refresh...`);
|
||||
const refreshed = await refreshAccessToken();
|
||||
if (refreshed) {
|
||||
console.log(`[API:${requestId}] Token refreshed, retrying request...`);
|
||||
// Retry with new token
|
||||
const newToken = await getAuthToken();
|
||||
headers['Authorization'] = `Bearer ${newToken}`;
|
||||
const retryResponse = await fetch(url, {
|
||||
const retryResponse = await fetchWithTimeout(url, {
|
||||
...options,
|
||||
headers,
|
||||
credentials: 'include'
|
||||
@@ -149,6 +172,7 @@ async function apiClient(endpoint, options = {}) {
|
||||
return handleResponse(retryResponse);
|
||||
} else {
|
||||
// Token refresh failed, clear auth
|
||||
console.error(`[API:${requestId}] Token refresh failed`);
|
||||
await clearAuth();
|
||||
throw new Error('Session expired. Please sign in again.');
|
||||
}
|
||||
@@ -156,7 +180,12 @@ async function apiClient(endpoint, options = {}) {
|
||||
|
||||
return handleResponse(response);
|
||||
} catch (error) {
|
||||
console.error(`[API] Request failed: ${endpoint}`, error);
|
||||
console.error(`[API:${requestId}] Request failed: ${endpoint}`, error);
|
||||
console.error(`[API:${requestId}] Error details:`, {
|
||||
message: error.message,
|
||||
name: error.name,
|
||||
stack: error.stack
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -282,16 +311,21 @@ export async function logout() {
|
||||
}
|
||||
|
||||
export async function getCurrentUser() {
|
||||
console.log('[AUTH] Getting current user...');
|
||||
try {
|
||||
// First check stored user
|
||||
console.log('[AUTH] Checking stored user...');
|
||||
const { value } = await Preferences.get({ key: STORAGE_KEYS.USER });
|
||||
if (value) {
|
||||
const user = JSON.parse(value);
|
||||
console.log('[AUTH] Found stored user:', user.email || user.id);
|
||||
|
||||
// Verify token is still valid by fetching fresh user data
|
||||
try {
|
||||
console.log('[AUTH] Fetching fresh user data from /api/me...');
|
||||
const freshUser = await apiClient('/api/me');
|
||||
if (freshUser) {
|
||||
console.log('[AUTH] Fresh user data received:', freshUser.email || freshUser.id);
|
||||
await Preferences.set({
|
||||
key: STORAGE_KEYS.USER,
|
||||
value: JSON.stringify(freshUser)
|
||||
@@ -300,23 +334,39 @@ export async function getCurrentUser() {
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[AUTH] Could not refresh user data:', e.message);
|
||||
console.log('[AUTH] Falling back to cached user data');
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
console.log('[AUTH] No stored user found');
|
||||
return null;
|
||||
} catch (e) {
|
||||
console.error('[AUTH] Failed to get current user:', e);
|
||||
console.error('[AUTH] Error details:', {
|
||||
message: e.message,
|
||||
name: e.name,
|
||||
stack: e.stack
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function isAuthenticated() {
|
||||
console.log('[AUTH] Checking authentication status...');
|
||||
const token = await getAuthToken();
|
||||
if (!token) return false;
|
||||
console.log('[AUTH] Token exists:', !!token);
|
||||
|
||||
if (!token) {
|
||||
console.log('[AUTH] No token found, user is not authenticated');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('[AUTH] Token found, fetching current user...');
|
||||
const user = await getCurrentUser();
|
||||
return !!user;
|
||||
const isAuth = !!user;
|
||||
console.log('[AUTH] Authentication result:', isAuth, user ? `(User: ${user.email || user.id})` : '');
|
||||
return isAuth;
|
||||
}
|
||||
|
||||
// OAuth helpers
|
||||
|
||||
Reference in New Issue
Block a user