first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
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',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Pragma': 'no-cache',
|
||||
},
|
||||
),
|
||||
) {
|
||||
_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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user