handleHttpBaseRequest<T> method
- BaseRequest request, {
- required DataOrFailureHandleResponse<
T> onResponse, - DataOrFailureHandleException<
T> ? onError, - List<
int> successStatuses = const [200, 201, 202, 203, 204], - bool debugRequestBody = true,
- bool overrideTextContentTypeHeader = true,
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));
}
}