Project

General

Profile

Task #28 » authenticated_client.dart

Milad Khnefes, 02/01/2026 12:07 PM

 
import 'package:http/http.dart' as http;
import 'package:sunnex/core/constants/urls.dart';
import 'package:sunnex/core/utils/client.dart';
import 'package:sunnex/data/contracts/database_contract.dart';
import 'package:sunnex/errors/invalid_access_token_exception.dart';
import 'package:sunnex/repository/auth_repository.dart';

class AuthenticatedApiClient extends ApiClient {
final AuthRepository authRepository;
final DatabaseContract databaseService;

AuthenticatedApiClient({
required this.authRepository,
required this.databaseService,
});

bool _refreshInProgress = false;

@override
Future<http.Response> sendRequest(
String partOfUrl, {
required String method,
String? body,
required bool retryOn401,
required bool isFirebaseCall,
}) async {
http.Response response = http.Response('{}', 408);

try {
final accessToken = await databaseService.getAccessToken();

final headers = {
'Accept-Encoding': 'gzip',
'Accept-Language': 'en',
if (method != 'GET') 'Content-Type': 'application/json',
if (accessToken != null) 'Authorization': 'Bearer $accessToken',
};

final baseUrl = URLs.fullApiUrl;
final url = partOfUrl.contains(URLs.version)
? partOfUrl
: (baseUrl + partOfUrl);

response = await executeRequest(url, method, headers, body: body);

if (response.statusCode == 401 && retryOn401) {
throw InvalidAccessTokenException();
}

return response;
} on InvalidAccessTokenException {
if (_refreshInProgress) rethrow;

_refreshInProgress = true;

try {
await authRepository.refreshTokens();

// retry once with new token
final newAccessToken = await databaseService.getAccessToken();

final retryHeaders = {
'Accept-Encoding': 'gzip',
'Accept-Language': 'en',
if (method != 'GET') 'Content-Type': 'application/json',
if (newAccessToken != null) 'Authorization': 'Bearer $newAccessToken',
};

final baseUrl = URLs.fullApiUrl;
final url = partOfUrl.contains(URLs.version)
? partOfUrl
: (baseUrl + partOfUrl);

return await executeRequest(url, method, retryHeaders, body: body);
} finally {
_refreshInProgress = false;
}
}
}
}
(10-10/12)