175 lines
4.8 KiB
Dart
175 lines
4.8 KiB
Dart
import 'package:dio/dio.dart';
|
|
import '../constants/app_constants.dart';
|
|
import '../errors/exceptions.dart';
|
|
|
|
/// API client for making HTTP requests using Dio
|
|
class ApiClient {
|
|
late final Dio _dio;
|
|
|
|
ApiClient() {
|
|
_dio = Dio(
|
|
BaseOptions(
|
|
baseUrl: AppConstants.apiBaseUrl,
|
|
connectTimeout: const Duration(milliseconds: AppConstants.connectionTimeout),
|
|
receiveTimeout: const Duration(milliseconds: AppConstants.receiveTimeout),
|
|
sendTimeout: const Duration(milliseconds: AppConstants.sendTimeout),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
),
|
|
);
|
|
|
|
// Add request/response interceptors for logging and error handling
|
|
_dio.interceptors.add(
|
|
InterceptorsWrapper(
|
|
onRequest: (options, handler) {
|
|
// Log request details in debug mode
|
|
handler.next(options);
|
|
},
|
|
onResponse: (response, handler) {
|
|
// Log response details in debug mode
|
|
handler.next(response);
|
|
},
|
|
onError: (error, handler) {
|
|
// Handle different types of errors
|
|
_handleDioError(error);
|
|
handler.next(error);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Make a GET request
|
|
Future<Response<T>> get<T>(
|
|
String path, {
|
|
Map<String, dynamic>? queryParameters,
|
|
Options? options,
|
|
CancelToken? cancelToken,
|
|
}) async {
|
|
try {
|
|
return await _dio.get<T>(
|
|
path,
|
|
queryParameters: queryParameters,
|
|
options: options,
|
|
cancelToken: cancelToken,
|
|
);
|
|
} on DioException catch (e) {
|
|
throw _handleDioError(e);
|
|
}
|
|
}
|
|
|
|
/// Make a POST request
|
|
Future<Response<T>> post<T>(
|
|
String path, {
|
|
dynamic data,
|
|
Map<String, dynamic>? queryParameters,
|
|
Options? options,
|
|
CancelToken? cancelToken,
|
|
}) async {
|
|
try {
|
|
return await _dio.post<T>(
|
|
path,
|
|
data: data,
|
|
queryParameters: queryParameters,
|
|
options: options,
|
|
cancelToken: cancelToken,
|
|
);
|
|
} on DioException catch (e) {
|
|
throw _handleDioError(e);
|
|
}
|
|
}
|
|
|
|
/// Make a PUT request
|
|
Future<Response<T>> put<T>(
|
|
String path, {
|
|
dynamic data,
|
|
Map<String, dynamic>? queryParameters,
|
|
Options? options,
|
|
CancelToken? cancelToken,
|
|
}) async {
|
|
try {
|
|
return await _dio.put<T>(
|
|
path,
|
|
data: data,
|
|
queryParameters: queryParameters,
|
|
options: options,
|
|
cancelToken: cancelToken,
|
|
);
|
|
} on DioException catch (e) {
|
|
throw _handleDioError(e);
|
|
}
|
|
}
|
|
|
|
/// Make a DELETE request
|
|
Future<Response<T>> delete<T>(
|
|
String path, {
|
|
dynamic data,
|
|
Map<String, dynamic>? queryParameters,
|
|
Options? options,
|
|
CancelToken? cancelToken,
|
|
}) async {
|
|
try {
|
|
return await _dio.delete<T>(
|
|
path,
|
|
data: data,
|
|
queryParameters: queryParameters,
|
|
options: options,
|
|
cancelToken: cancelToken,
|
|
);
|
|
} on DioException catch (e) {
|
|
throw _handleDioError(e);
|
|
}
|
|
}
|
|
|
|
/// Handle Dio errors and convert them to custom exceptions
|
|
Exception _handleDioError(DioException error) {
|
|
switch (error.type) {
|
|
case DioExceptionType.connectionTimeout:
|
|
case DioExceptionType.sendTimeout:
|
|
case DioExceptionType.receiveTimeout:
|
|
return const NetworkException('Connection timeout. Please check your internet connection.');
|
|
|
|
case DioExceptionType.badResponse:
|
|
final statusCode = error.response?.statusCode;
|
|
final message = error.response?.data?['message'] ?? 'Server error occurred';
|
|
|
|
if (statusCode != null) {
|
|
if (statusCode >= 400 && statusCode < 500) {
|
|
return ServerException('Client error: $message (Status: $statusCode)');
|
|
} else if (statusCode >= 500) {
|
|
return ServerException('Server error: $message (Status: $statusCode)');
|
|
}
|
|
}
|
|
return ServerException('HTTP error: $message');
|
|
|
|
case DioExceptionType.cancel:
|
|
return const NetworkException('Request was cancelled');
|
|
|
|
case DioExceptionType.connectionError:
|
|
return const NetworkException('No internet connection. Please check your network settings.');
|
|
|
|
case DioExceptionType.badCertificate:
|
|
return const NetworkException('Certificate verification failed');
|
|
|
|
case DioExceptionType.unknown:
|
|
default:
|
|
return ServerException('An unexpected error occurred: ${error.message}');
|
|
}
|
|
}
|
|
|
|
/// Add authorization header
|
|
void addAuthorizationHeader(String token) {
|
|
_dio.options.headers['Authorization'] = 'Bearer $token';
|
|
}
|
|
|
|
/// Remove authorization header
|
|
void removeAuthorizationHeader() {
|
|
_dio.options.headers.remove('Authorization');
|
|
}
|
|
|
|
/// Update base URL (useful for different environments)
|
|
void updateBaseUrl(String newBaseUrl) {
|
|
_dio.options.baseUrl = newBaseUrl;
|
|
}
|
|
} |