Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does flutter dio interceptor not invoking the method?

I am working on a flutter application which uses JWT to access backend endpoints. When the access token expires, I added an interceptor to refresh the token based on the solutions provided here: Using Interceptor in Dio for Flutter to Refresh Token I could see server logs which says 401.

Here is my code:

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:dummy/utils/config.dart';

Future<Response> uploadVideo(filePath, fileName, title, jwt) async {
  Dio dio = new Dio();
  var token = json.decode(jwt);
  dio.interceptors.clear();

  dio.options.headers["Authorization"] = "Bearer ${token['access']}";
  dio.interceptors.add(InterceptorsWrapper(onError: (error) async {
    print(error.response);
    if (error.response?.statusCode == 403 ||
     error.response?.statusCode == 401) {
    await refreshToken(jwt);
    _retry(error.request, dio);
     }
    return error.response;
  }));
  Response response;
  try {
    FormData formData = FormData.fromMap({
      "file_name": fileName,
      "content": await MultipartFile.fromFile(filePath),
      'title': title,
    });
    response = await dio.post("$BASE_URL/video/create/", data: formData);
    return response;
  } on DioError catch (e) {
    if (e.response) {
      print(e.response.data);
      print(e.response.headers);
      print(e.response.request);
    } else {
      // Something happened in setting up or sending the request that triggered an Error
      print(e.request);
      print(e.message);
    }
    return e.response;
  }
}

Future<Response<dynamic>> _retry(RequestOptions requestOptions, Dio dio) async {
  final options = new Options(
    method: requestOptions.method,
    headers: requestOptions.headers,
  );
  return dio.request<dynamic>(requestOptions.path,
      data: requestOptions.data,
      queryParameters: requestOptions.queryParameters,
      options: options);
}

Future<Response> refreshToken(jwt) async {
  print("COMING INSIDE");
  Dio dio = new Dio();
  var token = json.decode(jwt);
  var refreshToken = token['refresh'];
  Response response;
  try {
    FormData formData = FormData.fromMap({
      "refresh": refreshToken,
    });
    response = await dio.post("$BASE_URL/auth/login/refresh/", data: formData);
    return response;
  } catch (e) {
    return e.response;
  }
}

I tried with debugger as well, but its not executing the code after if statement where it checks for 401 and 403. Server clearly gives 401 as I am running it locally so I can see the logs.

What am I doing wrong here?

Thanks in advance.

like image 561
Maverick Avatar asked Mar 23 '21 15:03

Maverick


1 Answers

I think the problem is in your Interceptor:

dio.interceptors.add(InterceptorsWrapper(onError: (error) async {
    print(error.response);
    if (error.response?.statusCode == 403 ||
     error.response?.statusCode == 401) {
    await refreshToken(jwt);
    _retry(error.request, dio);
     }
    return error.response;
  }));

You're calling retry method, but:

  • you don't wait for result;
  • you return an error anyway.

Try to add return before _retry instead:

dio.interceptors.add(InterceptorsWrapper(onError: (error) async {
    print(error.response);
    if (error.response?.statusCode == 403 ||
     error.response?.statusCode == 401) {
    await refreshToken(jwt);
    return _retry(error.request, dio);
     }
    return error.response;
  }));
like image 103
Kirill Bubochkin Avatar answered Nov 09 '22 12:11

Kirill Bubochkin