Flutter Custom Interceptors code here, it is showing error on onRequest Method as well as onResponse Method and onError Method. recently started flutter implementation.
class AppInterceptors extends Interceptor {
Dio _dio = Dio();
SharedPreferences _prefs;
TokenAnalyzer _tokenAnalyzer;
AppInterceptors(this._dio, this._tokenAnalyzer);
#override
Future<dynamic> onRequest(RequestOptions options) async {
_prefs = await _sharedPreferences;
var accessToken = _prefs.get("access_token") ?? '';
return options;
}
#override
Future<dynamic> onResponse(Response options) async {
return options;
}
#override
Future<dynamic> onError(DioError dioError) async {
if (dioError.type == DioErrorType.response &&
dioError.response.statusCode < 200 ||
dioError.response.statusCode > 400) {
if (dioError.response.statusCode == 500) {
prefs.setString("ErrorMessage", dioError.response.data);
errorService.showErrorMessage(dioError.response.data);
throw (dioError.response.data);
} else if (dioError.response.statusCode == 401) {
var _prefs = await _sharedPreferences;
prefs.setString("ErrorMessage", dioError.response.data);
}
}
return null;
}
Here it is another file implemented DIO instillation
class DioHttpClient {
Dio _dio = Dio();
BaseOptions options = new BaseOptions(
receiveTimeout: 1000 * 60,
headers: {'Content-Type': 'application/json', 'Authorization': ''});
DioHttpClient(TokenAnalyzer tokenAnalyzer) {
_dio = new Dio(options);
_dio.interceptors.add(AppInterceptors(_dio, tokenAnalyzer));
}
Dio get HttpClient {
return _dio;
}
}
API Call Code below:
Dio _httpClient1 = Dio();
Future<T> post<T>(url, body, {allowAnnoymous = false}) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
try {
print("called new post method $url");
clientService.isBusy = true;
String token = prefs.get("AccessToken");
Response response = await _httpClient1.post<T>(url,
data: jsonEncode(body),
options: Options(headers: {
"allowanonymous": allowAnnoymous.toString(),
'Authorization': 'Bearer $token',
}));
print("==================== success post");
throwError(response);
return response.data;
} catch (ex) {
throwErrorMessage();
throw ex;
}
}
I am getting below error and it is showing error Like this
'AppInterceptors.onRequest' ('Future<dynamic> Function(RequestOptions)') isn't a valid override of 'Interceptor.onRequest' ('void Function(RequestOptions, RequestInterceptorHandler)').
Could you please help me anyone !! thanks Advance !!!
Error says it all:
'AppInterceptors.onRequest' ('Future<dynamic> Function(RequestOptions)') isn't a valid override of 'Interceptor.onRequest' ('void Function(RequestOptions, RequestInterceptorHandler)').
You have
Future<dynamic> Function(RequestOptions)
Shoud be
void Function(RequestOptions, RequestInterceptorHandler)
See example.
You have missed RequestInterceptorHandler in arguments of onRequest method.
override
Future<dynamic> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
_prefs = await _sharedPreferences;
var accessToken = _prefs.get("access_token") ?? '';
return
options;
}
You will have to change all the three overridden method's declaration ( onError, onResponse, and onRequest), with like something below:
import 'package:dio/dio.dart';
class Intercept extends Interceptor {
#override // add errorInterceptorHandler param
Future<dynamic> onError(DioError error, errorInterceptorHandler) async {
// replace with your logic
if (error.type == DioErrorType.connectTimeout ||
error.type == DioErrorType.response) {
print(error.response);
print("CONNECTION TIMEOUT");
}
return error;
}
#override // add responseInterceptorHandler param
Future<dynamic> onResponse(Response response, responseInterceptorHandler) async {
// replace with your logic
if (response.statusCode == 200) {
print("RESPONSE--------->");
print(response.data);
print("<--------------------");
}
return response;
}
#override // add requestInterceptorHandler param
Future<dynamic> onRequest(RequestOptions request, requestInterceptorHandler) async {
// replace with your logic
print("REQUESTING--------->");
print(request.headers);
print("<--------------------");
return request;
}
}
Related
I am trying to implement a JWT Access/Refresh token flow with flutter. After my access token expires, my QueuedInterceptor gets a new access token with the refresh token. Everything works fine, but it is not retrying to get the requested ressource and returns a 401. After a refresh of that page, the resource loads. How do I implement a retry with QueuedInterceptor ?
class AuthInterceptor extends QueuedInterceptor {
final Dio _dio;
AuthInterceptor(this._dio);
#override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
final accessToken = await storage.read(key: "accessToken");
final refreshToken = await storage.read(key: "refreshToken");
if (accessToken == null || refreshToken == null) {
const AuthState.unauthenticated();
final error = DioError(requestOptions: options, type: DioErrorType.other);
return handler.reject(error);
}
final accessTokenHasExpired = JwtDecoder.isExpired(accessToken);
final refreshTokenHasExpired = JwtDecoder.isExpired(refreshToken);
var _refreshed = true;
if (refreshTokenHasExpired) {
const AuthState.unauthenticated();
final error = DioError(requestOptions: options, type: DioErrorType.other);
return handler.reject(error);
} else if (accessTokenHasExpired) {
// regenerate new access token
_refreshed = await _regenerateAccessToken();
}
if (_refreshed) {
options.headers["Authorization"] = "Bearer $accessToken";
return handler.next(options);
} else {
final error = DioError(requestOptions: options, type: DioErrorType.other);
return handler.reject(error);
}
}
Future<bool> _regenerateAccessToken() async {
try {
var dio = Dio();
final refreshToken = await storage.read(key: "refreshToken");
final response = await dio.post(
"https://localhost:7104/api/Login/Token/Refresh",
options: Options(headers: {"Authorization": "Bearer $refreshToken"}),
);
if (response.statusCode == 200 || response.statusCode == 201) {
final newAccessToken = response.data["accessToken"];
storage.write(key: "accessToken", value: newAccessToken);
return true;
} else if (response.statusCode == 401 || response.statusCode == 403) {
const AuthState.unauthenticated();
return false;
} else {
return false;
}
} on DioError {
return false;
} catch (e) {
return false;
}
}
}
This is how I create the request with the interceptor. It throws a 401 if my access token is expired:
final dio = Dio();
dio.options.baseUrl = authenticationBackend;
dio.interceptors.addAll([
AuthInterceptor(dio),
]);
var response = await dio.get('$host/animals');
class RefreshTokenInterceptor extends Interceptor {
final Dio dio;
RefreshTokenInterceptor({
required this.dio,
});
#override
void onError(DioError err, ErrorInterceptorHandler handler) async {
if (err.response == null) {
return;
}
if (err.response!.statusCode == 401) {
var res = await refreshToken();
if (res != null && res) {
await _retry(err.requestOptions);
}
}
return handler.next(err);
}
/// Api to get new token from refresh token
///
Future<bool?> refreshToken() async {
///call your refesh token api here
}
/// For retrying request with new token
///
Future<Response<dynamic>> _retry(RequestOptions requestOptions) async {
final options = Options(
method: requestOptions.method,
headers: requestOptions.headers,
);
return dio.request<dynamic>(requestOptions.path,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters,
options: options);
}
}
And then use it
dio.interceptors.addAll(
[
/// interceptor for refreshing token
///
RefreshTokenInterceptor(dio: dio),
],
);
I have an interceptor to send jwt token and to use the refresh_token endpoint when the jwt expires.
With an expired jwt I get
Error: Bad state: Future already completed
error, but the request is processed right anyway. In the console I see one successful response and one with 401 error afterward. How can I solve this issue?
custom_interceptor.dart
class CustomInterceptor extends DefaultInterceptor {
ISecureStorage secureStorageService = ISecureStorage();
#override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
LoginModel loginModel = await secureStorageService.readLoginModel();
options.headers = {
"Content-type": "application/json",
"Authorization": "Bearer ${loginModel.access_token}"
};
return super.onRequest(options, handler);
}
#override
void onError(err, handler) async {
if (err.response?.statusCode == 401) {
final Dio _dio = DioConfig().dio;
LoginModel loginModel = await secureStorageService.readLoginModel();
Uri uri = Uri.https(
"$BASE_URL", "/refresh_token_url");
try {
await _dio.postUri(uri, data: {
"refresh_token": loginModel.refresh_token,
"grant_type": "refresh_token"
}).then((value) async {
if (value?.statusCode == 200) {
await secureStorageService.deleteLoginModel();
LoginModel newLoginData = LoginModel.fromJson(value.data);
await secureStorageService.saveLoginModel(loginModel: newLoginData);
err.requestOptions.headers["Authorization"] =
"Bearer " + newLoginData.refresh_token;
final opts = new Options(
method: err.requestOptions.method,
headers: err.requestOptions.headers);
final cloneReq = await _dio.request(err.requestOptions.path,
options: opts,
data: err.requestOptions.data,
queryParameters: err.requestOptions.queryParameters);
return handler.resolve(cloneReq);
}
return err;
});
return super.onError(err, handler);
} catch (e, st) {
print("ERROR: " + e);
print("STACK: " + st.toString());
return super.onError(err, handler);
}
} else {
return super.onError(err, handler);
}
}
}
class DefaultInterceptor extends Interceptor {
#override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
print(
'REQUEST[${options.method}] => PATH: ${options.path} | DATA => ${options.data} | JWT => ${options.headers}');
return super.onRequest(options, handler);
}
#override
void onResponse(Response response, ResponseInterceptorHandler handler) {
print(
'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path} | DATA => ${response.data}');
super.onResponse(response, handler);
return;
}
#override
void onError(DioError err, ErrorInterceptorHandler handler) async {
print(
'ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path} | SENT_DATA => ${err.requestOptions.data} | RECEIVED_DATA => ${err.response?.data}');
return super.onError(err, handler);
}
}
dio_config.dart
class DioConfig {
static DioConfig _singletonHttp;
Dio _dio;
get dio => _dio;
factory DioConfig() {
_singletonHttp ??= DioConfig._singleton();
return _singletonHttp;
}
DioConfig._singleton() {
_dio = Dio();
}
dispose() {
_dio.close();
}
}
i_secure_storage.dart
abstract class ISecureStorage {
factory ISecureStorage() => getSecureStorage();
Future<LoginModel> readLoginModel() async => LoginModel.empty;
Future<bool> saveLoginModel({LoginModel loginModel}) async => false;
Future<bool> deleteLoginModel() async => false;
}
web_secure_storage.dart
ISecureStorage getSecureStorage() => WebSecureStorageService();
class WebSecureStorageService implements ISecureStorage {
final String _loginData = 'loginData';
html.Storage webStorage = html.window.localStorage;
#override
Future<LoginModel> readLoginModel() async {
return webStorage[_loginData] == null
? LoginModel.empty
: LoginModel.fromJson(jsonDecode(webStorage[_loginData]));
}
#override
Future<bool> saveLoginModel({ LoginModel loginModel}) async {
webStorage[_loginData] = jsonEncode(loginModel);
return true;
}
#override
Future<bool> deleteLoginModel() async {
webStorage.remove(_loginData);
return true;
}
}
mobile_secure_storage.dart
ISecureStorage getSecureStorage() => MobileSecureStorageService();
class MobileSecureStorageService implements ISecureStorage {
final String _loginModel = 'loginModel';
FlutterSecureStorage storage = const FlutterSecureStorage();
#override
Future<LoginModel> readLoginModel() async {
try {
dynamic _loginData = await storage.read(key: _loginModel);
return _loginData == null ? LoginModel.empty : LoginModel.fromJson(jsonDecode(_loginData));
} on PlatformException catch (ex) {
throw PlatformException(code: ex.code, message: ex.message);
}
}
#override
Future<bool> saveLoginModel({LoginModel loginModel}) async {
try {
await storage.write(key: _loginModel, value: jsonEncode(loginModel));
return true;
} on PlatformException catch (ex) {
throw PlatformException(code: ex.code, message: ex.message);
}
}
#override
Future<bool> deleteLoginModel() async {
try {
await storage.delete(key: _loginModel);
return true;
} on PlatformException catch (ex) {
throw PlatformException(code: ex.code, message: ex.message);
}
}
}
EDIT:
IN MY CASE the problem was in the first
return super.onError(err, handler);
It must be return null;
So I got it working
You are using Dio for the requests. Version 4.0.6 of Dio which is the most recent version as of today has this known issue. Please refer to the same on GitHub here.
Solution
Downgrade your Dio package to the last stable version that was known to not have this issue until a new version is released.
In your pubspec.yaml.
dio: 4.0.4
Then get packages again.
> flutter pub get
For anyone else having this issue and it is not solved by only downgrading dio: Downgrade dio to 4.0.4 AND remove connectTimeout from your BaseOptions.
Update 13/02/23:
dio v5.0.0 finally contains a fix for this issue.
Details: At the end flutter-china has transferred the ownership of the dio repo to CFUG and all the changes from the diox hard fork have been merged into the original dio repo, including the fix for this issue.
Update 15/12/22:
diox is a hard fork of dio made by CFUG group with the aim of keeping dio well maintained. In diox, this issue has already been fixed.
Original answer:
Related issue: https://github.com/flutterchina/dio/issues/1480
There are several open PRs that (try to) tackle this bug:
https://github.com/flutterchina/dio/pull/1470
https://github.com/flutterchina/dio/pull/1496
https://github.com/flutterchina/dio/pull/1550
https://github.com/flutterchina/dio/pull/1565
If you do not want to downgrade to dio 4.0.4 as other answers suggest, you can depend on some of these forks until one of them is merged into the official repository.
In my case, I've reviewed and tested #ipcjs's solution and seems to be working as expected:
dio:
git:
url: https://github.com/ipcjs/dio
path: dio/
ref: b77af132442bf3266ccf11b50ce909711455db3a
class InterceptorsWrapper extends QueuedInterceptorsWrapper {
#override
void onRequest(RequestOptions options,RequestInterceptorHandler handler){
log('send request:${options.baseUrl}${options.path}');
final accessToken = Storage.instance.box.read("accessToken");
options.headers['Authorization'] = 'Bearer $accessToken';
super.onRequest(options, handler);
}
#override
void onError(DioError err, ErrorInterceptorHandler handler) {
switch (err.type) {
case DioErrorType.connectTimeout:
case DioErrorType.sendTimeout:
case DioErrorType.receiveTimeout:
throw DeadlineExceededException(err.requestOptions);
case DioErrorType.response:
switch (err.response?.statusCode) {
case 400:
throw BadRequestException(err.requestOptions);
case 401:
throw UnauthorizedException(err.requestOptions);
case 404:
throw NotFoundException(err.requestOptions);
case 409:
throw ConflictException(err.requestOptions);
case 500:
throw InternalServerErrorException(err.requestOptions);
}
break;
case DioErrorType.cancel:
break;
case DioErrorType.other:
throw NoInternetConnectionException(err.requestOptions);
}
super.onError(err, handler);
}
}
...
...
This is how I done my Dio Interceptor,
you don't have to return anything in your void onRequest() simply call super.onRequest() and don't use handler instance in interceptor class like
return handler.resolve(cloneReq);
that part is already done inside onRequest(). I solved my problem in this way
you can also try.
thank you.
To instantly solve this problem just comment out the "connectTimeOut" field from DioBaseOptions as follows:
connectTimeout: 30000,
To solve this error, I did like that
void onError(DioError err, ErrorInterceptorHandler handler) async {
//Halding refresh token other logic
//Future.delay solve my error.
Future.delayed(const Duration(seconds: 5), () => super.onError(err,handler));
}
I tried refreshing my tokens when my calling api goes to error 401 (token expires) but when it calls dio interceptor is not triggered.
api.dart is definition of my dio
Dio _createHttpClient() {
final api = Dio(
new BaseOptions(
baseUrl: environments.api,
contentType: Headers.jsonContentType,
responseType: ResponseType.json,
),
);
api
..interceptors.clear()
..interceptors.add(new ErrorDialogInterceptor())
..interceptors.add(new AuthTokenInterceptor(api));
return api;
}
final api = _createHttpClient();
profil_provider.dart is the call of my api
Future<ProfilePicture?> getPictureProfile(String id) async {
String url = '/v1/users/$id/profile-picture';
try {
final response = await api.get(
url,
options: Options(
responseType: ResponseType.bytes,
headers: {
ErrorDialogInterceptor.skipHeader: true,
},
),
);
Uint8List avatar = Uint8List.fromList(response.data);
return ProfilePicture(image: avatar);
} catch (e) {
print('e');
return null;
}
}
and it go to the catch error
auth_interceptor.dart is for manage my error and request of my api
class AuthTokenInterceptor extends Interceptor {
static const skipHeader = 'skipAuthToken';
Dio api;
AuthTokenInterceptor(this.api);
#override
onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
final context = applicationKey.currentContext;
print("test");
final repository = context?.read<AuthRepository>();
if (repository == null) {
return;
}
final accessToken = await repository.getAccessToken();
print("access: $accessToken");
if (accessToken != null) {
print(accessToken);
options.headers['Authorization'] = 'Bearer $accessToken';
}
return super.onRequest(options, handler);
}
#override
onError(DioError err, ErrorInterceptorHandler handler) async {
final context = applicationKey.currentContext;
if (context == null) {
return;
}
final response = err.response?.data;
if (response == null) {
return super.onError(err, handler);
}
final repository = context.read<AuthRepository>();
if (err.response?.statusCode == 401)
if (err.response?.statusCode == 401 &&
await repository.getRefreshToken() != null) {
api.interceptors.clear();
return _handlerRefreshToken(context, repository, err, handler);
}
return super.onError(err, handler);
}
and it not go to the auth interceptor with my debug print, I don't know why it not go there with the error 401 from the catch error
you can do.
// returns the http request
Future<Response<ProfilePicture>> getPictureProfile(String id) {
String url = '/v1/users/$id/profile-picture';
return api.get(url)
}
//...
// and use a try/catch outside the method
try{
Response<ProfilePicture> respose = await getPictureProfile(555)
print(respose.data)
}catch(e){
print(e)
}
I have created a DioClient class to handle all API calls but for some reason, the onResponse and onError callbacks are not firing. However, the onRequest callback does fire. What am I doing wrong?
Here's my Dio client:
class DioClient{
final Function(DioError error) onError;
final Function(Response response) onSuccess;
final Function(dynamic error) onTimeout;
final Function onNoNetworkConnection;
final String url;
final baseUrl = "https://google.com/app";
final bool authenticatedRequest;
String token = "";
Dio _dio;
DioClient({this.onError, this.onSuccess, this.onTimeout, this.onNoNetworkConnection, this.url, this.authenticatedRequest = false});
onRequest(RequestOptions options, RequestInterceptorHandler handler){
if(authenticatedRequest){
print('requested');
options.headers["Authorization"] = "Bearer " + token;
}
}
setUp() async{
_dio = Dio();
if(authenticatedRequest){
UserDBHelper userDBHelper = UserDBHelper();
User user = await userDBHelper.getUser();
token = user.toMap()['token'];
}
//_dio.interceptors.clear();
// _dio.interceptors
// .add(ApiInterceptors());
_dio.options.baseUrl = baseUrl;
// return _dio;
}
get() async{
Dio dio = await setUp();
dio.get(url);
}
post(data) async{
Dio dio = await setUp();
var response = await _dio.post(url, data: data);
}
}
And here's my custom interceptor class:
class ApiInterceptors extends Interceptor {
#override
Future<dynamic> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
print('requesting');
// do something before request is sent
}
#override
Future<dynamic> onError(DioError dioError, ErrorInterceptorHandler handler) async {
//handler.next(dioError);
print('done');
// do something to error
}
#override
Future<dynamic> onResponse(Response response, ResponseInterceptorHandler handler) async {
print(response.statusCode);
print('error');
// do something before response
}
}
Sending a post request with the post function prints requesting to the console. However neither error (from the onRespnse callback) nor done (from the onError callback) is printed to the console.
Here's the Controller from which I am sending the request:
class AuthLogin {
SharedPreferences prefs;
final String email;
final String password;
final Function onWrongLogins;
final Function onUnVerified;
final Function onNoNetwork;
AuthLogin(
{
this.email,
this.password,
this.onWrongLogins,
this.onUnVerified,
this.onNoNetwork
}){
loginUser();
}
Map<String, dynamic> toMap(){
return{
'email': email,
'password': password
};
}
onError(DioError error){
var errors = error;
}
onSuccess(Response response){
var res = response;
}
loginUser() async{
DioClient dioClient = DioClient(url: login, onSuccess: onSuccess, onError: onError);
dioClient.post(toMap());
}
}
Also note that when I remove the Interceptor from the Dio setup, it functions as it should and I do get either a response or an error.
Please I'd really appreciate any help I can get.
Add a call to super class methods in your ApiInterceptors class. Below is an example of your ApiInterceptors class.
class ApiInterceptors extends Interceptor {
#override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
print('requesting');
// do something before request is sent
super.onRequest(options, handler); //add this line
}
#override
void onError(DioError dioError, ErrorInterceptorHandler handler) {
//handler.next(dioError);
print('done');
// do something to error
super.onError(dioError, handler); //add this line
}
#override
void onResponse(Response response, ResponseInterceptorHandler handler) {
print(response.statusCode);
print('error');
// do something before response
super.onResponse(response, handler); //add this line
}
}
I have declared a class to make api requests using flutter Dio as follows.
class DioUtil {
static Dio _instance;
static Dio getInstance() {
if (_instance == null) {
_instance = createDio();
}
return _instance;
}
static Dio createDio() {
var dio = Dio();
dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
// Do something before request is sent
return handler.next(options); //continue
}, onResponse: (response, handler) {
// Do something with response data
return handler.next(response); // continue
}, onError: (DioError e, handler) async {
if (e.response != null) {
if (e.response.statusCode == 401) {
var dio = DioUtil.getInstance();
dio.interceptors.requestLock.lock();
dio.interceptors.responseLock.lock();
RequestOptions requestOptions = e.requestOptions;
await refreshToken();
Repository repository = Repository();
var accessToken = await repository.readData("accessToken");
final opts = new Options(
method: requestOptions.method
);
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.interceptors.requestLock.unlock();
dio.interceptors.responseLock.unlock();
dio.request(requestOptions.path,
options: opts,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
}//TODO: handle else clause
}
}));
return dio;
}
static refreshToken() async {
Response response;
Repository repository = Repository();
var dio = Dio();
final Uri apiUrl = Uri.parse(BASE_PATH + "auth/reIssueAccessToken");
var refreshToken = await repository.readData("refreshToken");
dio.options.headers["Authorization"] = "Bearer " + refreshToken;
response = await dio.postUri(apiUrl);
if (response.statusCode == 200) {
LoginResponse loginResponse =
LoginResponse.fromJson(jsonDecode(response.toString()));
repository.addValue('accessToken', loginResponse.data.accessToken);
repository.addValue('refreshToken', loginResponse.data.refreshToken);
} else {
print(response.toString());
}
}
}
and I use flutter bloc pattern and my bloc is as follows.
class OurClassBloc extends Bloc<OurClassEvent, OurClassState> {
OurClassBloc(OurClassState initialState) : super(initialState);
Repository repository = Repository();
#override
Stream<OurClassState> mapEventToState(
OurClassEvent event,
) async* {
if (event is GetClasses) {
yield* _getClassCategories(event);
}
}
Stream<OurClassState> _getClassCategories(GetClasses event) async* {
Response response;
var dio = DioUtil.getInstance();
final String apiUrl = (BASE_PATH + "classCategories");
var accessToken = await repository.readData("accessToken");
Map<String, dynamic> map = {"active": event.active};
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";
try {
response = await dio.get(apiUrl, queryParameters: map);
if (response.statusCode == 200) {
OurClassResponse loginResponse =
OurClassResponse.fromJson(jsonDecode(response.toString()));
yield OurClassSuccess(loginResponse);
}
if (response.statusCode >= 400) {
yield OurClassFailed();
}
} catch (e) {
yield OurClassFailed();
}
}
}
When I make the requests with valid access token, I get 200 status code in bloc class and api works fine.when the token is expired, the dio class correctly gets the new token, make the same api call with new token successfully and inside the below callback I get the correct response also.
onResponse: (response, handler) {
return handler.next(response);
}
but response doesn't comes to bloc class. Though it returned the response by calling return handler.next(response);,it is not coming to response variable inside _getClassCategories method.I expect the correct response should come to the response variable in bloc class for both scenarios:
makes the api call with valid token.
makes the api call with expired token.
but only scenario 1 is working in my code and hope someone here can help me to fix this.
EDIT- this works fine with dio previous version(3.0.10) - code
dio.request(requestOptions.path,
options: opts,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
This line creates a new request with no relation to the original one. If the request succeeds, there is no code listening for a response. If you want the original caller to receive anything, you will need to forward the response to the original handler:
try {
final response = await dio.request(requestOptions.path,
options: opts,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
handler.resolve(response);
} on DioError catch (error) {
handler.next(error); // or handler.reject(error);
}
Also, be sure to forward the error to the handler in non-401 cases as well. Dio 4.0.0 interceptors don't automatically forward anything.