request<T> method
Future<T>
request<T>({
- required String endpoint,
- required HttpMethod method,
- Object? body,
- Map<
String, String> ? headers, - required T fromJson(),
override
Performs an asynchronous network request and decodes the JSON response.
This method automatically retries failed requests up to _maxRetries times
using an exponential backoff strategy.
Parameters:
endpoint: The API path (e.g., "/api/links").method: The HttpMethod for the request.body: Optional object to be sent as a JSON request body.headers: Optional map of additional HTTP headers.fromJson: A factory function to transform the response JSON into typeT.
Throws a LinkFortyError (e.g., NetworkError, InvalidResponseError) if the request ultimately fails.
Implementation
@override
Future<T> request<T>({
required String endpoint,
required HttpMethod method,
Object? body,
Map<String, String>? headers,
required T Function(Map<String, dynamic>) fromJson,
}) async {
LinkFortyError? lastError;
for (var attempt = 1; attempt <= _maxRetries; attempt++) {
try {
return await _performRequest<T>(
endpoint: endpoint,
method: method,
body: body,
headers: headers,
fromJson: fromJson,
);
} catch (e) {
// If it's already a LinkFortyError (from above rethrow), just rethrow it
if (e is LinkFortyError) {
rethrow;
}
// Otherwise wrap it
lastError = NetworkError(e);
// Exponential backoff: 1s, 2s, 4s
if (attempt < _maxRetries) {
final delaySeconds = math.pow(2.0, attempt - 1).toInt();
LinkFortyLogger.log(
'Request failed (attempt $attempt/$_maxRetries), retrying in ${delaySeconds}s... Error: $e',
);
await Future.delayed(Duration(seconds: delaySeconds));
}
}
}
throw lastError ??
NetworkError(Exception('Request failed after $_maxRetries attempts'));
}