postWithRetry static method
Makes a POST request with timeout and retry support.
url - The target URL.
headers - Request headers.
body - Request body.
timeout - Request timeout (default: 60s).
maxRetries - Maximum retry attempts (default: 3).
retryDelay - Base delay between retries (default: 2s).
Implementation
static Future<http.Response> postWithRetry(
Uri url, {
Map<String, String>? headers,
Object? body,
Duration timeout = HttpConfig.defaultTimeout,
int maxRetries = HttpConfig.defaultMaxRetries,
Duration retryDelay = HttpConfig.defaultRetryDelay,
}) async {
Exception? lastException;
for (var attempt = 0; attempt <= maxRetries; attempt++) {
try {
final response = await http
.post(url, headers: headers, body: body)
.timeout(timeout, onTimeout: () {
throw RequestTimeoutException(
message: 'Request to $url timed out',
timeout: timeout,
);
});
// Check for rate limiting
if (response.statusCode == 429) {
final retryAfter = _parseRetryAfter(response.headers['retry-after']);
throw RateLimitException(
message: 'Rate limit exceeded',
retryAfter: retryAfter,
);
}
// Success
if (response.statusCode >= 200 && response.statusCode < 300) {
return response;
}
// Server error - retry
if (response.statusCode >= 500 && attempt < maxRetries) {
await _waitWithBackoff(attempt, retryDelay);
continue;
}
// Client error - don't retry
return response;
} on RequestTimeoutException {
lastException = RequestTimeoutException(
message: 'Request to $url timed out after $attempt retries',
timeout: timeout,
);
if (attempt < maxRetries) {
await _waitWithBackoff(attempt, retryDelay);
continue;
}
} on RateLimitException catch (e) {
lastException = e;
if (attempt < maxRetries) {
final waitDuration =
e.retryAfter ?? _calculateBackoff(attempt, retryDelay);
await Future<void>.delayed(waitDuration);
continue;
}
} catch (e) {
lastException = e is Exception ? e : Exception(e.toString());
if (attempt < maxRetries) {
await _waitWithBackoff(attempt, retryDelay);
continue;
}
}
}
throw lastException ?? Exception('Unknown error during HTTP request');
}