Files
hidalyx-drluiscastro/lib/core/network/api_client.dart
T

83 lines
2.6 KiB
Dart
Raw Normal View History

2026-09-21 16:33:51 -04:00
import 'package:dio/dio.dart';
typedef TokenRefreshCallback = Future<String?> Function();
class ApiClient {
static const String baseUrl = 'https://api.hidalyx.com';
static final ApiClient _instance = ApiClient._internal();
factory ApiClient() => _instance;
final Dio dio;
TokenRefreshCallback? onTokenRefresh;
ApiClient._internal({Dio? customDio})
: dio = customDio ??
Dio(
BaseOptions(
baseUrl: baseUrl,
connectTimeout: const Duration(seconds: 15),
receiveTimeout: const Duration(seconds: 15),
headers: {
'Content-Type': 'application/json',
},
),
) {
_setupInterceptors();
}
ApiClient.withDio(this.dio) {
_setupInterceptors();
}
void _setupInterceptors() {
dio.interceptors.add(
QueuedInterceptorsWrapper(
onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
final path = options.path;
if (path.contains('/auth/login')) {
// NUNCA enviar Authorization header en el endpoint de login
options.headers.remove('Authorization');
}
return handler.next(options);
},
onError: (DioException err, ErrorInterceptorHandler handler) async {
final statusCode = err.response?.statusCode;
final path = err.requestOptions.path;
final isAuthEndpoint = path.contains('/auth/login') ||
path.contains('/auth/refresh') ||
path.contains('/auth/logout');
final isExpiredOrUnauthorized = statusCode == 401 ||
(statusCode == 403 &&
err.response?.data?.toString().contains('TOKEN_EXPIRED') == true);
if (isExpiredOrUnauthorized && !isAuthEndpoint && onTokenRefresh != null) {
try {
final newToken = await onTokenRefresh!();
if (newToken != null && newToken.isNotEmpty) {
setAuthToken(newToken);
final requestOptions = err.requestOptions;
requestOptions.headers['Authorization'] = 'Bearer $newToken';
final retryResponse = await dio.fetch(requestOptions);
return handler.resolve(retryResponse);
}
} catch (_) {
// Si el refresh falla, continuar el flujo del error normal
}
}
return handler.next(err);
},
),
);
}
void setAuthToken(String token) {
dio.options.headers['Authorization'] = 'Bearer $token';
}
void clearAuthToken() {
dio.options.headers.remove('Authorization');
}
}