call static method

Future<void> call(
  1. String url,
  2. RequestType requestType, {
  3. Map<String, dynamic>? headers,
  4. Map<String, dynamic>? queryParameters,
  5. required dynamic onSuccess(
    1. Response response
    ),
  6. dynamic onError(
    1. ApiException error
    )?,
  7. dynamic onReceiveProgress(
    1. int value,
    2. int progress
    )?,
  8. dynamic onSendProgress(
    1. int total,
    2. int progress
    )?,
  9. Function? onLoading,
  10. CancelToken? cancelToken,
  11. dynamic data,
})

perform safe api request

Implementation

static Future<void> call(
  String url,
  RequestType requestType, {
  Map<String, dynamic>? headers,
  Map<String, dynamic>? queryParameters,
  required Function(Response response) onSuccess,
  Function(ApiException error)? onError,
  Function(int value, int progress)? onReceiveProgress,
  Function(int total, int progress)?
  onSendProgress, // while sending (uploading) progress
  Function? onLoading,
  CancelToken? cancelToken,
  dynamic data,
}) async {
  try {
    // 1) indicate loading state
    await onLoading?.call();
    // 2) try to perform http request
    late Response response;
    if (requestType == RequestType.get) {
      response = await _dio.get(
        url,
        onReceiveProgress: onReceiveProgress,
        queryParameters: queryParameters,
        options: Options(headers: headers),
      );
    } else if (requestType == RequestType.post) {
      response = await _dio.post(
        url,
        data: data,
        onReceiveProgress: onReceiveProgress,
        onSendProgress: onSendProgress,
        queryParameters: queryParameters,
        options: Options(headers: headers),
        cancelToken: cancelToken,
      );
    } else if (requestType == RequestType.put) {
      response = await _dio.put(
        url,
        data: data,
        onReceiveProgress: onReceiveProgress,
        onSendProgress: onSendProgress,
        queryParameters: queryParameters,
        options: Options(headers: headers),
      );
    } else if (requestType == RequestType.patch) {
      response = await _dio.patch(
        url,
        data: data,
        onReceiveProgress: onReceiveProgress,
        onSendProgress: onSendProgress,
        queryParameters: queryParameters,
        options: Options(headers: headers),
      );
    } else {
      response = await _dio.delete(
        url,
        data: data,
        queryParameters: queryParameters,
        options: Options(headers: headers),
      );
    }
    await onSuccess(response);
  } on DioException catch (error) {
    final _RetryableApiCall retryable = _RetryableApiCall(
      url: url,
      requestType: requestType,
      headers: headers == null ? null : Map<String, dynamic>.from(headers),
      queryParameters: queryParameters == null
          ? null
          : Map<String, dynamic>.from(queryParameters),
      data: data,
    );
    final int? statusCode = error.response?.statusCode;
    if (statusCode == 401) {
      _track401FailedCall(retryable);
      // If the host already updated the token shortly before this late 401,
      // immediately retry once instead of waiting for another refresh.
      final bool hasActiveGate = _authRefreshCompleter != null;
      final bool tokenUpdatedRecently = _lastAuthTokenUpdatedAt != null &&
          DateTime.now().difference(_lastAuthTokenUpdatedAt!) <
              _authRefreshWaitTimeout;

      if (!hasActiveGate && tokenUpdatedRecently) {
        try {
          final Response retryResponse = await _executeRequestForRetry(
            url,
            requestType,
            headers: headers,
            queryParameters: queryParameters,
            data: data,
            onReceiveProgress: onReceiveProgress,
            onSendProgress: onSendProgress,
            cancelToken: cancelToken,
          );
          _untrack401FailedCall(retryable);
          await onSuccess(retryResponse);
          return;
        } on DioException catch (lateError) {
          final int? lateStatusCode = lateError.response?.statusCode;
          if (lateStatusCode == 401) {
            // Token is still not accepted; fall back to the normal gate
            // flow (which will emit a new authError cycle if needed).
          } else {
            _handleDioError(error: lateError, url: url, onError: onError);
            return;
          }
        }
      }

      await _handleAuth401AndRetry(
        error: error,
        url: url,
        requestType: requestType,
        headers: headers,
        queryParameters: queryParameters,
        data: data,
        onReceiveProgress: onReceiveProgress,
        onSendProgress: onSendProgress,
        cancelToken: cancelToken,
        onSuccess: onSuccess,
        onError: onError,
        trackedCall: retryable,
      );
      return;
    }
    _handleDioError(error: error, url: url, onError: onError);
  } on SocketException {
    _handleSocketException(url: url, onError: onError);
  } on TimeoutException {
    _handleTimeoutException(url: url, onError: onError);
  } catch (error) {
    _handleUnexpectedException(url: url, onError: onError, error: error);
  }
}