request method
Future<ResponseModal>
request({
- required ApiMethod method,
- required String url,
- dynamic requestData,
- Map<
String, dynamic> ? headers, - void authTokenCallback()?,
- Map<
String, dynamic> ? queryParameters, - bool useWithoutToken = false,
- bool cacheResponse = false,
- Duration cacheDuration = const Duration(minutes: 30),
- bool forceOffline = false,
- CancelToken? cancelToken,
- void onSendProgress()?,
- void onReceiveProgress()?,
- BuildContext? context,
- bool showSuccessMessage = false,
- bool showErrorMessage = true,
- bool showErrorLog = true,
- bool showSuccessLog = true,
Implementation
Future<ResponseModal> request({
required ApiMethod method,
required String url,
dynamic requestData,
Map<String, dynamic>? headers,
void Function()? authTokenCallback,
Map<String, dynamic>? queryParameters,
bool useWithoutToken = false,
bool cacheResponse = false,
Duration cacheDuration = const Duration(minutes: 30),
bool forceOffline = false,
CancelToken? cancelToken,
void Function(int, int)? onSendProgress,
void Function(int, int)? onReceiveProgress,
BuildContext? context,
bool showSuccessMessage = false,
bool showErrorMessage = true,
bool showErrorLog = true,
bool showSuccessLog = true,
}) async
{
try {
// Check if we should force offline mode
if (forceOffline) {
print('Force offline mode enabled');
if (!_enableCache) {
print('Cache not enabled, cannot use offline mode');
throw {'error': 'Cache not enabled, cannot use offline mode'};
}
final cached = _cacheBox.get(url);
if (cached != null) return cached['data'] ?? cached;
print('No cached data available');
throw {'error': 'No cached data available'};
}
// Make the request
late Response response;
final options = Options(
headers: headers,
extra: {
'useWithoutToken': useWithoutToken,
'cacheResponse': cacheResponse,
'cacheDuration': cacheDuration.inMilliseconds,
},
);
switch (method) {
case ApiMethod.get:
response = await _dio.get(
url,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
break;
case ApiMethod.post:
response = await _dio.post(
url,
data: requestData,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
);
break;
case ApiMethod.put:
response = await _dio.put(
url,
data: requestData,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
);
break;
case ApiMethod.patch:
response = await _dio.patch(
url,
data: requestData,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
);
break;
case ApiMethod.delete:
response = await _dio.delete(
url,
data: requestData,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
);
break;
}
// Cache response if needed
if (_enableCache && cacheResponse) {
await _cacheBox.put(
url,
response.data,
);
}
final responseModal = ResponseModal.fromDioResponse(response);
if (showSuccessLog) {
log('Response is ${responseModal.data}');
}
log('loklklklklkl is ${responseModal.data}');
if (responseModal.status == 1 && showSuccessMessage) {
_showSnackbar(context, responseModal.message, isError: false);
} else if (responseModal.status == 0 && showErrorMessage) {
_showSnackbar(context, responseModal.message, isError: true);
}
return responseModal;
} on DioException catch (e) {
// Create a detailed error log message
// final errorLog = '''
// ╔═══════════════════════════════════════════════════════════════
// ║ Dio Exception Occurred
// ╟───────────────────────────────────────────────────────────────
// ║ Type: ${}
// ║ Error: ${e.error}
// ║ Message: ${e.message}
// �═══════════════════════════════════════════════════════════════
// ║ Request:
// ║ URL: ${e.requestOptions.uri}
// ║ Method: ${e.requestOptions.method}
// ║ Headers: ${e.requestOptions.headers}
// ╟───────────────────────────────────────────────────────────────
// ║ Response:
// ║ Status: ${e.response?.statusCode}
// ║ Data: ${e.response?.data}
// ║ Headers: ${e.response?.headers}
// ╚═══════════════════════════════════════════════════════════════
// ''';
if (showErrorLog) {
log("Dio Exception Message: ${e.message}, ");
log("Dio Exception Occurred Error: ${e.error}, Status: ${e.response?.statusCode}, Data: ${e.response?.data}, ");
}
// Handle response errors
if (e.response != null) {
try {
final errorResponse = e.response?.data;
final statusCode = e.response?.statusCode;
// Special handling for 401 Unauthorized
if (statusCode == 401) {
authTokenCallback?.call();
log(
'⚠️ Authorization failed. Status: 401. Response: $errorResponse');
final message = errorResponse is Map
? errorResponse['message'] ??
'Session expired. Please login again.'
: 'Session expired. Please login again.';
if (showErrorMessage) {
_showSnackbar(context, message, isError: true);
}
return ResponseModal(
message: message,
data: errorResponse is Map ? (errorResponse['data'] ?? {}) : {},
status: 0,
error: errorResponse is Map ? (errorResponse['error'] ??
{'code': 'unauthorized'}) : {'code': 'unauthorized'},
fullData: errorResponse ?? {},
);
}
// Handle other error responses with message
if (errorResponse is Map) {
final message = errorResponse['message'] ??
errorResponse['error']?['hint'] ??
'Request failed with status $statusCode';
if (showErrorMessage) {
_showSnackbar(context, message, isError: true);
}
return ResponseModal(
message: message,
data: errorResponse['data'] ?? {},
status: errorResponse['status'] ?? 0,
error: errorResponse['error'] ??
{'code': 'unknown_error', 'status': statusCode},
fullData: errorResponse,
);
}
} catch (parseError) {
log('❌ Error parsing error response: $parseError');
}
}
// Handle specific error types
switch (e.type) {
case DioExceptionType.connectionError:
_showSnackbar(context, 'No internet connection');
return ResponseModal(
message: 'No internet connection',
data: {},
status: 0,
error: {'code': 'no_internet'},
fullData: {},
);
case DioExceptionType.connectionTimeout:
case DioExceptionType.sendTimeout:
case DioExceptionType.receiveTimeout:
_showSnackbar(context, 'Request timeout. Please try again.');
return ResponseModal(
message: 'Request timeout',
data: {},
status: 0,
error: {'code': 'timeout'},
fullData: {},
);
case DioExceptionType.badCertificate:
log('🔒 SSL Certificate Error: ${e.error}');
_showSnackbar(context, 'Secure connection failed');
return ResponseModal(
message: 'Secure connection failed',
data: {},
status: 0,
error: {'code': 'ssl_error', 'details': e.error.toString()},
fullData: {},
);
default:
final userMessage = kDebugMode
? e.message ?? 'An error occurred'
: 'Something went wrong. Please try again.';
if (kDebugMode) {
_showSnackbar(context, userMessage, isError: true);
}
return ResponseModal(
message: userMessage,
data: {},
status: 0,
error: {
'code': 'unknown_error',
'type': e.type.toString(),
'details': e.error?.toString()
},
fullData: e.response?.data ?? {},
);
}
} catch (e, stackTrace) {
log('''
╔═══════════════════════════════════════════════════════════════
║ Unhandled Exception
╟───────────────────────────────────────────────────────────────
║ Error: $e
║ Stack Trace: $stackTrace
╚═══════════════════════════════════════════════════════════════
''');
final errorModal = ResponseModal(
message: kDebugMode ? e.toString() : 'An unexpected error occurred',
data: {},
status: 0,
error: {
'code': 'unhandled_exception',
'details': e.toString(),
'stackTrace': kDebugMode ? stackTrace.toString() : null
},
fullData: {},
);
if (kDebugMode) {
_showSnackbar(context, e.toString());
}
return errorModal;
}
}