postWithRetry static method

Future<Response> postWithRetry(
  1. Uri url, {
  2. Map<String, String>? headers,
  3. Object? body,
  4. Duration timeout = HttpConfig.defaultTimeout,
  5. int maxRetries = HttpConfig.defaultMaxRetries,
  6. Duration retryDelay = HttpConfig.defaultRetryDelay,
})

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');
}