-
Notifications
You must be signed in to change notification settings - Fork 362
Description
Devtools is not showing the HTTP calls on network tab. I use dio package 4.0.6 version for making HTTP calls
DevTools version: 2.37.3
Connected Device:
CPU / OS: arm64 (64 bit) android
Connected app type: Flutter native (debug build)
Dart Version: 3.5.4
Flutter Version: 3.24.5 / stable
Framework / Engine: dec2ee5c1f / a18df97ca5
This is the api_client.dart I use for endpoint calls
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../../common/utils/flushbar_utils.dart';
import '../api_end_points/uri_constants.dart';
import 'custom_interceptor.dart';
import 'models/request_object.dart';
class APIClient {
late Dio? _dio;
static final _defaultTimeout =
const Duration(minutes: kReleaseMode ? 3 : 6).inMilliseconds;
Map<String, String> get _addAuthHeader => {'add_auth_header': 'true'};
APIClient({
Dio? dio,
CustomInterceptor? customInterceptor,
}) {
_dio = dio ??
Dio(BaseOptions(
receiveTimeout: _defaultTimeout, connectTimeout: _defaultTimeout));
// if (kDebugMode) {
// rootBundle.loadString('assets/certs/dev-certs.pem').then((data) {
// // final bytes = utf8.encode(data);
// // final securityContext = SecurityContext(withTrustedRoots: true)
// // ..setTrustedCertificatesBytes(bytes);
// final securityContext = SecurityContext(withTrustedRoots: true);
// _client = client ?? HttpClient(context: securityContext);
// (_dio!.httpClientAdapter as DefaultHttpClientAdapter)
// .onHttpClientCreate = (_) => _client;
// });
// }
_dio!.interceptors.add(customInterceptor ?? CustomInterceptor());
}
Future<Map<String, dynamic>> get(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
try {
return await _dio!
.get<dynamic>(
requestObject.getPath(),
options: Options(
headers: requestObject.headers ?? {},
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
queryParameters: requestObject.queryParameters ?? {},
)
.then(processResponse);
} on DioError catch (e) {
final fullPath = e.requestOptions.uri.path;
final path = fullPath.split('/').skip(2).join('/');
// If path starts with /, add it back
final cleanPath = path.startsWith('/') ? path : '/$path';
// Check if this is the endpoint to skip
print('checkCleanPath $cleanPath');
// Define this at the top of your get method or as a class-level constant
final List<String> skipErrorHandlingGetEndpoints = [
URIConstants.getUserByEmailId
];
// Then use it like this:
if (skipErrorHandlingGetEndpoints.contains(cleanPath)) {
// Rethrow the exception to handle it from where endpoint was being called
rethrow;
}
// final List<String> skipFlushbarGetEndpoints = [URIConstants.addFCMTokenByEmail];
// final bool skipFlushbar = skipFlushbarGetEndpoints.contains(cleanPath);
const bool skipFlushbar = false;
// Handle DioError based on status code
if (e.response != null) {
final statusCode = e.response!.statusCode;
switch (statusCode) {
case 400:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Bad Request: Missing or invalid parameters'}'
);
}
throw Exception('Bad Request: Missing or invalid parameters');
case 403:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Forbidden: Your email is not authorized to access this resource'}'
);
}
throw Exception('Forbidden: Your email is not authorized to access this resource');
case 404:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Not Found: The requested data was not found in the database'}'
);
}
throw Exception('Not Found: The requested data was not found in the database');
case 500:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Internal Server Error: Something went wrong on the server'}'
);
}
throw Exception('Internal Server Error: Something went wrong on the server');
default:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Request failed'}'
);
}
throw Exception('Request failed with status: $statusCode');
}
} else {
// Handle errors without response (network errors, timeouts, etc.)
if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.receiveTimeout) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection timeout: Please check your internet connection'
);
throw Exception('Connection timeout: Please check your internet connection');
} else if (e.type == DioErrorType.other) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection error: Unable to connect to the server'
);
throw Exception('Connection error: Unable to connect to the server');
} else {
await FlushbarUtils.show(
messageType: MessageType.error,
'Network error: ${e.message}'
);
throw Exception('Network error: ${e.message}');
}
}
} catch (e) {
// Handle any other unexpected errors (but don't catch our own thrown Exceptions)
if (e is Exception && e.toString().contains('Exception:')) {
// Re-throw our own exceptions
rethrow;
}
await FlushbarUtils.show(
messageType: MessageType.error,
'An unexpected error occurred: ${e.toString()}'
);
throw Exception('An unexpected error occurred: ${e.toString()}');
}
}
Future<bool> getFlag(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
return _dio!
.get<dynamic>(
requestObject.getPath(),
options: Options(
headers: requestObject.headers ?? {},
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
queryParameters: requestObject.queryParameters ?? {},
)
.then(processFlagResponse);
}
Future<Response<List>> getBytes(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
return _dio!.get<List<int>>(
requestObject.getPath(),
options: Options(
headers: requestObject.headers ?? {},
sendTimeout: requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
responseType: ResponseType.bytes,
followRedirects: false,
validateStatus: (status) {
return status == 200;
}),
);
}
Future<Map<String, dynamic>> postMultiPartFile(RequestObject requestObject, {bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
dynamic dataToSend = requestObject.payload;
if (dataToSend is Map<String, dynamic> && dataToSend.containsKey('file') && dataToSend['file'] is File) {
final File file = dataToSend['file'];
final String fileName = file.path.split('/').last;
final FormData formData = FormData.fromMap({
...dataToSend..remove('file'),
'file': await MultipartFile.fromFile(file.path, filename: fileName),
});
dataToSend = formData;
}
return _dio!
.post<dynamic>(
requestObject.getPath(),
data: dataToSend,
options: Options(
headers: requestObject.headers ?? {},
sendTimeout: requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout: requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
)
.then(processResponse);
}
Future<Map<String, dynamic>> post(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
try {
return await _dio!
.post<dynamic>(
requestObject.getPath(),
data: requestObject.payload,
options: Options(
headers: requestObject.headers ?? {},
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
)
.then(processResponse);
} on DioError catch (e) {
final fullPath = e.requestOptions.uri.path;
final path = fullPath.split('/').skip(2).join('/');
// If path starts with /, add it back
final cleanPath = path.startsWith('/') ? path : '/$path';
// Define this at the top of your get method or as a class-level constant
final List<String> skipErrorHandlingPostEndpoints = [
URIConstants.evaluation
];
// Then use it like this:
if (skipErrorHandlingPostEndpoints.contains(cleanPath)) {
// Rethrow the exception to handle it from where endpoint was being called
rethrow;
}
// final List<String> skipFlushbarPostEndpoints = [URIConstants.addFCMTokenByEmail];
// final bool skipFlushbar = skipFlushbarPostEndpoints.contains(cleanPath);
const bool skipFlushbar = false;
// Handle DioError based on status code
if (e.response != null) {
final statusCode = e.response!.statusCode;
switch (statusCode) {
case 400:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Bad Request: Missing or invalid parameters'}'
);
}
throw Exception('Bad Request: Missing or invalid parameters');
case 403:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Forbidden: Your email is not authorized to access this resource'}'
);
}
throw Exception('Forbidden: Your email is not authorized to access this resource');
case 404:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Not Found: The requested data was not found in the database'}'
);
}
throw Exception('Not Found: The requested data was not found in the database');
case 500:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Internal Server Error: Something went wrong on the server'}'
);
}
throw Exception('Internal Server Error: Something went wrong on the server');
default:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Request failed'}'
);
}
throw Exception('Request failed with status: $statusCode');
}
} else {
// Handle errors without response (network errors, timeouts, etc.)
if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.receiveTimeout) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection timeout: Please check your internet connection'
);
throw Exception('Connection timeout: Please check your internet connection');
} else if (e.type == DioErrorType.other) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection error: Unable to connect to the server'
);
throw Exception('Connection error: Unable to connect to the server');
} else {
await FlushbarUtils.show(
messageType: MessageType.error,
'Network error: ${e.message}'
);
throw Exception('Network error: ${e.message}');
}
}
} catch (e) {
// Handle any other unexpected errors (but don't catch our own thrown Exceptions)
if (e is Exception && e.toString().contains('Exception:')) {
// Re-throw our own exceptions
rethrow;
}
await FlushbarUtils.show(
messageType: MessageType.error,
'An unexpected error occurred: ${e.toString()}'
);
throw Exception('An unexpected error occurred: ${e.toString()}');
}
}
Future<Map<String, dynamic>> postFormData(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
return _dio!
.post<dynamic>(
requestObject.getPath(),
data: requestObject.rawPayload,
options: Options(
headers: requestObject.headers,
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
)
.then(processResponse);
}
Future<Map<String, dynamic>> put(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
try {
return await _dio!
.put<dynamic>(
requestObject.getPath(),
data: requestObject.payload,
options: Options(
headers: requestObject.headers ?? {},
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
)
.then(processResponse);
} on DioError catch (e) {
final fullPath = e.requestOptions.uri.path;
final path = fullPath.split('/').skip(2).join('/');
// If path starts with /, add it back
final cleanPath = path.startsWith('/') ? path : '/$path';
// Define this at the top of your get method or as a class-level constant
final List<String> skipErrorHandlingPutEndpoints = [
URIConstants.updateCart
];
// Then use it like this:
if (skipErrorHandlingPutEndpoints.contains(cleanPath)) {
// Rethrow the exception to handle it from where endpoint was being called
rethrow;
}
final List<String> skipFlushbarPutEndpoints = [URIConstants.addFCMTokenByEmail];
final bool skipFlushbar = skipFlushbarPutEndpoints.contains(cleanPath);
// Handle DioError based on status code
if (e.response != null) {
final statusCode = e.response!.statusCode;
switch (statusCode) {
case 400:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Bad Request: Missing or invalid parameters'}'
);
}
throw Exception('Bad Request: Missing or invalid parameters');
case 403:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Forbidden: Your email is not authorized to access this resource'}'
);
}
throw Exception('Forbidden: Your email is not authorized to access this resource');
case 404:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Not Found: The requested data was not found in the database'}'
);
}
throw Exception('Not Found: The requested data was not found in the database');
case 500:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Internal Server Error: Something went wrong on the server'}'
);
}
throw Exception('Internal Server Error: Something went wrong on the server');
default:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Request failed'}'
);
}
throw Exception('Request failed with status: $statusCode');
}
} else {
// Handle errors without response (network errors, timeouts, etc.)
if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.receiveTimeout) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection timeout: Please check your internet connection'
);
throw Exception('Connection timeout: Please check your internet connection');
} else if (e.type == DioErrorType.other) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection error: Unable to connect to the server'
);
throw Exception('Connection error: Unable to connect to the server');
} else {
await FlushbarUtils.show(
messageType: MessageType.error,
'Network error: ${e.message}'
);
throw Exception('Network error: ${e.message}');
}
}
} catch (e) {
// Handle any other unexpected errors (but don't catch our own thrown Exceptions)
if (e is Exception && e.toString().contains('Exception:')) {
// Re-throw our own exceptions
rethrow;
}
await FlushbarUtils.show(
messageType: MessageType.error,
'An unexpected error occurred: ${e.toString()}'
);
throw Exception('An unexpected error occurred: ${e.toString()}');
}
}
Future<Map<String, dynamic>> patch(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
return _dio!
.patch<dynamic>(
requestObject.getPath(),
data: requestObject.payload,
options: Options(
headers: requestObject.headers ?? {},
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
)
.then(processResponse);
}
Future<Map<String, dynamic>> delete(RequestObject requestObject,
{bool protected = false}) async {
if (protected) {
requestObject.headers?.addAll(_addAuthHeader);
}
try {
return await _dio!
.delete<dynamic>(
requestObject.getPath(),
data: requestObject.payload,
options: Options(
headers: requestObject.headers ?? {},
sendTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
receiveTimeout:
requestObject.timeout?.inMilliseconds ?? _defaultTimeout,
),
)
.then(processResponse);
} on DioError catch (e) {
final fullPath = e.requestOptions.uri.path;
final path = fullPath.split('/').skip(2).join('/');
// If path starts with /, add it back
final cleanPath = path.startsWith('/') ? path : '/$path';
// Define this at the top of your get method or as a class-level constant
final List<String> skipErrorHandlingDeleteEndpoints = [
URIConstants.deleteUserAccount
];
// Then use it like this:
if (skipErrorHandlingDeleteEndpoints.contains(cleanPath)) {
// Rethrow the exception to handle it from where endpoint was being called
rethrow;
}
// final List<String> skipFlushbarDeleteEndpoints = [URIConstants.addFCMTokenByEmail];
// final bool skipFlushbar = skipFlushbarDeleteEndpoints.contains(cleanPath);
const bool skipFlushbar = false;
// Handle DioError based on status code
if (e.response != null) {
final statusCode = e.response!.statusCode;
switch (statusCode) {
case 400:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Bad Request: Missing or invalid parameters'}'
);
}
throw Exception('Bad Request: Missing or invalid parameters');
case 403:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Forbidden: Your email is not authorized to access this resource'}'
);
}
throw Exception('Forbidden: Your email is not authorized to access this resource');
case 404:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Not Found: The requested data was not found in the database'}'
);
}
throw Exception('Not Found: The requested data was not found in the database');
case 500:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Internal Server Error: Something went wrong on the server'}'
);
}
throw Exception('Internal Server Error: Something went wrong on the server');
default:
if(!skipFlushbar) {
await FlushbarUtils.show(
messageType: MessageType.error,
'$cleanPath : $statusCode ${e.response!.statusMessage ?? 'Request failed'}'
);
}
throw Exception('Request failed with status: $statusCode');
}
} else {
// Handle errors without response (network errors, timeouts, etc.)
if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.receiveTimeout) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection timeout: Please check your internet connection'
);
throw Exception('Connection timeout: Please check your internet connection');
} else if (e.type == DioErrorType.other) {
await FlushbarUtils.show(
messageType: MessageType.error,
'Connection error: Unable to connect to the server'
);
throw Exception('Connection error: Unable to connect to the server');
} else {
await FlushbarUtils.show(
messageType: MessageType.error,
'Network error: ${e.message}'
);
throw Exception('Network error: ${e.message}');
}
}
} catch (e) {
// Handle any other unexpected errors (but don't catch our own thrown Exceptions)
if (e is Exception && e.toString().contains('Exception:')) {
// Re-throw our own exceptions
rethrow;
}
await FlushbarUtils.show(
messageType: MessageType.error,
'An unexpected error occurred: ${e.toString()}'
);
throw Exception('An unexpected error occurred: ${e.toString()}');
}
}
Map<String, dynamic> processResponse(Response response) {
if (response.data == '' || response.data == null) {
return <String, dynamic>{'statusCode': response.statusCode};
} else {
if (response.data is List) {
return <String, dynamic>{'data': response.data};
} else if (response.data is String) {
return <String, dynamic>{'data': response.data};
} else {
return response.data as Map<String, dynamic>;
}
}
}
bool processFlagResponse(Response response) {
if (response.data == '' || response.data == null) {
return false;
} else {
if (response.data is bool) {
return response.data;
} else {
return false;
}
}
}
}
This is my CustomInterceptor.dart
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
class CustomInterceptor extends Interceptor {
@OverRide
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
if (kDebugMode) {
debugPrint('REQUEST[${options.method}] => PATH: ${options.path}');
}
return super.onRequest(options, handler);
}
@OverRide
void onResponse(
Response response, ResponseInterceptorHandler handler) {
if (kDebugMode) {
debugPrint(
'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');
}
return super.onResponse(response, handler);
}
@OverRide
void onError(DioError err, ErrorInterceptorHandler handler) {
if (kDebugMode) {
debugPrint(
'ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
}
return super.onError(err, handler);
}
}