runable
This commit is contained in:
175
lib/core/network/api_client.dart
Normal file
175
lib/core/network/api_client.dart
Normal file
@@ -0,0 +1,175 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user