import 'package:http/http.dart' as http; import '../../features/auth/data/datasources/auth_local_datasource.dart'; import '../../features/auth/domain/repositories/auth_repository.dart'; import '../errors/exceptions.dart'; class AuthenticatedClient extends http.BaseClient { final http.Client _inner; final AuthLocalDataSource _localDataSource; final AuthRepository _authRepository; AuthenticatedClient({ required AuthLocalDataSource localDataSource, required AuthRepository authRepository, http.Client? inner, }) : _localDataSource = localDataSource, _authRepository = authRepository, _inner = inner ?? http.Client(); @override Future send(http.BaseRequest request) async { final tokens = await _localDataSource.getTokens(); if (tokens != null) { request.headers['Authorization'] = 'Bearer ${tokens.accessToken}'; } var response = await _inner.send(request); if (response.statusCode == 401 && tokens != null) { final refreshResult = await _authRepository.refreshToken(); final refreshed = refreshResult.when( success: (_) => true, error: (_) => false, ); if (refreshed) { final newTokens = await _localDataSource.getTokens(); if (newTokens != null) { final newRequest = _copyRequest(request, newTokens.accessToken); response = await _inner.send(newRequest); } } else { await _localDataSource.clearAll(); throw const UnauthorizedException(message: 'Session expired'); } } return response; } http.BaseRequest _copyRequest(http.BaseRequest original, String token) { final http.Request newRequest = http.Request(original.method, original.url) ..headers.addAll(original.headers) ..headers['Authorization'] = 'Bearer $token'; if (original is http.Request && original.body.isNotEmpty) { newRequest.body = original.body; } return newRequest; } @override void close() { _inner.close(); super.close(); } }