Last active
June 25, 2024 20:21
-
-
Save Collins-01/f717ff3c2f3ebe8796b85a71c140f821 to your computer and use it in GitHub Desktop.
Refresh Token Implementation In Flutter, using Dio plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:bod_pay/core/core.dart'; | |
| import 'package:bod_pay/core/network_service/refresh_token_interceptor.dart'; | |
| import 'package:bod_pay/utils/utils.dart'; | |
| import 'package:dio/dio.dart'; | |
| import 'network_request_exception.dart'; | |
| class NetworkServiceInterceptors extends Interceptor { | |
| final _logger = const AppLogger(NetworkServiceInterceptors); | |
| final LocalCache cache = LocalCacheImpl(); | |
| @override | |
| void onError(DioException err, ErrorInterceptorHandler handler) async { | |
| _logger.e("Error from Dio: ", | |
| functionName: "onError", error: err.toString()); | |
| if (err.response?.statusCode != null) { | |
| _logger.e("Error ===> ${err.response}"); | |
| switch (err.response?.statusCode) { | |
| case 400: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Bad Request Error', | |
| ); | |
| break; | |
| case 401: | |
| refreshToken(() => handler.next(err)); | |
| break; | |
| case 403: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Conflict Error', | |
| ); | |
| break; | |
| case 404: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Not Found Error', | |
| ); | |
| break; | |
| case 409: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Conflict Error', | |
| ); | |
| break; | |
| case 500: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Internal Server Error', | |
| ); | |
| break; | |
| case 503: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Internal Server Error', | |
| ); | |
| break; | |
| default: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Request Unknown Error', | |
| ); | |
| } | |
| } else { | |
| switch (err.type) { | |
| case DioExceptionType.connectionError: | |
| case DioExceptionType.sendTimeout: | |
| case DioExceptionType.receiveTimeout: | |
| case DioExceptionType.connectionTimeout: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Network Error', | |
| ); | |
| break; | |
| case DioExceptionType.badCertificate: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Network Error', | |
| ); | |
| break; | |
| case DioExceptionType.badResponse: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Bad Request Error', | |
| ); | |
| break; | |
| case DioExceptionType.cancel: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Network Error', | |
| ); | |
| break; | |
| case DioExceptionType.unknown: | |
| err = NetworkRequestException( | |
| err.requestOptions, | |
| err.response, | |
| 'Network Error', | |
| ); | |
| break; | |
| } | |
| } | |
| return handler.next(err); | |
| } | |
| @override | |
| void onRequest(RequestOptions options, RequestInterceptorHandler handler) { | |
| return handler.next(options); | |
| } | |
| @override | |
| void onResponse(Response response, ResponseInterceptorHandler handler) { | |
| // TODO: implement onResponse | |
| super.onResponse(response, handler); | |
| } | |
| } | |
| void checkStatusCode( | |
| RequestOptions requestOptions, | |
| Response? response, | |
| ) async { | |
| try { | |
| switch (response?.statusCode) { | |
| case 200: | |
| case 204: | |
| case 201: | |
| break; | |
| case 400: | |
| throw NetworkRequestException( | |
| requestOptions, | |
| response, | |
| 'Bad Request Error', | |
| ); | |
| case 401: | |
| throw NetworkRequestException( | |
| requestOptions, | |
| response, | |
| 'UnAuthorized Error', | |
| ); | |
| case 404: | |
| throw NetworkRequestException( | |
| requestOptions, | |
| response, | |
| 'Not Found Error', | |
| ); | |
| case 409: | |
| throw NetworkRequestException( | |
| requestOptions, | |
| response, | |
| 'Conflict Error', | |
| ); | |
| case 500: | |
| throw NetworkRequestException( | |
| requestOptions, | |
| response, | |
| 'Internal Server Error', | |
| ); | |
| default: | |
| throw NetworkRequestException( | |
| requestOptions, | |
| response, | |
| 'Internal Server Error', | |
| ); | |
| } | |
| } on Failure { | |
| rethrow; | |
| } | |
| } | |
| // refresh token method | |
| Future<void> refreshToken(Function()? callback) async { | |
| final LocalCache localCache = LocalCacheImpl(); | |
| try { | |
| print("REFRESHING TOKEN"); | |
| final token = await localCache.getToken(); | |
| if (token == null) { | |
| // TODO: Logout and clear cache | |
| NavigationService.instance | |
| .navigateToReplaceAll(RoutePaths.loginOrRegisterView); | |
| localCache.clearCache(); | |
| return; | |
| } | |
| final response = await http.get(Uri.parse( | |
| "${APIEndPoints.base_url}${APIEndPoints.refreshToken}${token.refreshToken}")); | |
| print("Response from calling refresh token => ${response.body}"); | |
| /// check if the tokens were returned, cache and navigate. | |
| if (response.statusCode == 200) { | |
| /// cache token | |
| final decodedBody = jsonDecode(response.body) as Map<String, dynamic>; | |
| final data = Token.fromMap(decodedBody['Data']); | |
| localCache.saveToken(data); | |
| return; | |
| } | |
| ///check if the response code if 401, it means refresh token has expired, logout. | |
| if (response.statusCode == 401) { | |
| NavigationService.instance | |
| .navigateToReplaceAll(RoutePaths.loginOrRegisterView); | |
| localCache.clearCache(); | |
| throw CustomException( | |
| errorTitle: "", msg: "session has expired, please relogin"); | |
| } | |
| /// NO CONDITION IS MET, LOGOUT | |
| else { | |
| NavigationService.instance | |
| .navigateToReplaceAll(RoutePaths.loginOrRegisterView); | |
| localCache.clearCache(); | |
| throw CustomException( | |
| errorTitle: "", msg: "session has expired, please relogin"); | |
| } | |
| /// check response, cache tokens, | |
| } catch (e) { | |
| log("error refreshing token ==> $e"); | |
| callback?.call(); | |
| // NavigationService.instance | |
| // .navigateToReplaceAll(RoutePaths.loginOrRegisterView); | |
| // localCache.clearCache(); | |
| // throw CustomException( | |
| // errorTitle: "", msg: "session has expired, please relogin"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment