handleHttpBaseRequest<T> method

  1. @override
Future<Either<Failure, T>> handleHttpBaseRequest<T>(
  1. BaseRequest request, {
  2. required DataOrFailureHandleResponse<T> onResponse,
  3. DataOrFailureHandleException<T>? onError,
  4. List<int> successStatuses = const [200, 201, 202, 203, 204],
  5. bool debugRequestBody = true,
  6. bool overrideTextContentTypeHeader = true,
})
override

Provides you with an easy way to handle a BaseRequest This helper provides you more control over the type of request being send it will help you with some boilerplate needed when implementing handling http request following our architecture It also provides early access to the request details before performing the request so it be better for logging request its commonly the return type of a HttpClient in most of its methods (get, post, patch, put, etc)

onResponse is required in order for you to process your server's custom response and return the value you need, this callback is triggered only if the response status code returned by the server is part of the successStatuses set, otherwise this helper will throw and process it as a ServerFailure

onError can be provided to handle a specific exception on your repo/service, if you return null, it will be interpreted as not handled and the function will proceed to handle it itself

successStatuses let you define what status will be considered as a successful response so your response will be delegated to the onResponse callback By default this value is [200, 201, 202, 203, 204]

debugRequestBody let you specify if this method should log the body passed to the API, sometime you may want to keep it secret if you are submitting sensitive information Defaults to true

Implementation

@override
Future<Either<Failure, T>> handleHttpBaseRequest<T>(
  BaseRequest request, {
  required DataOrFailureHandleResponse<T> onResponse,
  DataOrFailureHandleException<T>? onError,
  List<int> successStatuses = const [200, 201, 202, 203, 204],
  bool debugRequestBody = true,

  /// When creating an standalone [Request] class instance
  /// defaults Content-Type it's set to 'text/plain' if not specified otherwise
  /// most of the times user would like to send 'application/json'
  /// so if this flag is set to true, this will override the header to 'application/json' just if
  /// current header is of type 'text/plain'
  bool overrideTextContentTypeHeader = true,
}) async {
  failureCbk(Failure failure) {
    return Left<Failure, T>(failure);
  }

  rightCbk(T result) {
    return Right<Failure, T>(result);
  }

  try {
    try {
      if (client == null) {
        throw MissingHttpClientException();
      }

      if (overrideTextContentTypeHeader) {
        _overrideTextRequestHeader(request);
      }

      logger.t("Performing request to ${request.url}");

      if (debugRequestBody) {
        _logRequestBody(request);
      }

      final streamedResponse = await client!.send(request);

      final response = await Response.fromStream(streamedResponse);

      logger.t("Response Body was: ${response.body}");

      if (successStatuses.contains(response.statusCode)) {
        return await onResponse(response, failureCbk, rightCbk);
      }

      throw ServerException.fromResponse(response);
    } catch (error, stackTrace) {
      // check if user have a specific handler for this exception
      final Either<Failure, T>? handle = onError?.call(error, failureCbk, rightCbk, stackTrace);
      if (handle != null) {
        return handle;
      }
      logger.t("Error not handled by user, so handling by default this impl");
      // if it was not handled then rethrow so we handle it ourselves
      rethrow;
    }
  } on ServerException catch (error, stackTrace) {
    logger.e("ServerFailure", error: error, stackTrace: stackTrace);
    return left<Failure, T>(
      ServerFailure.fromServerException(error),
    );
  } on SocketException catch (error, stackTrace) {
    logger.e("InternetConnectionIssueFailure", error: error, stackTrace: stackTrace);
    return left<Failure, T>(
      InternetConnectionIssueFailure.fromSocketException(error),
    );
  } catch (error, stackTrace) {
    logger.e("UnknownFailure", error: error, stackTrace: stackTrace);
    return left<Failure, T>(UnknownFailure.fromException(error));
  }
}