2

I am testing out dio and tried to add a interceptor to simply add a token to future requests but am getting a weird results I can't seem to fix. All I have as a test is a 2 buttons. One when clicked should log me in and add the token to the interceptor, and the second button requests the auth profile data. For some reason, clicking the log in button I log in fine but get a 403 Forbidden when clicking the second button to access the auth profile data (even though i request the profile data after adding the interceptor). The weird part is that when i click the second button again (without changing any code or even hot reloading) everything works fine and the auth profile data is printed out. Every time I hot restart I get back to this same problem where my first request of the auth profile data has a 403 but subsequent requests work fine. I've been trying to figure out what is going on for a couple hours and cannot understand whats wrong. Please help. Thank you. (The backend is handled by django but the problem cannot be there as the api works with other frameworks and even in dio works fine on subsequent button presses, just not the first)

Code


class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  Dio session = Dio(
    BaseOptions(
      connectTimeout: 30000,
      baseUrl: 'http://127.0.0.1:8000',
      responseType: ResponseType.json,
      contentType: ContentType.json.toString(),
    ),
  );
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            RaisedButton(
                child: Text('Log In'),
                onPressed: () async {
                  print('starting');
                  var res = await session.post('/auth/login/',
                      data: {'username': 'tester', 'password': 'tester'});
                  print(res.data);
                  session.interceptors.clear();
                  session.interceptors.addAll([
                    InterceptorsWrapper(
                      onRequest: (RequestOptions requestOptions) {
                        session.interceptors.requestLock.lock();
                        String token = res.data['key'];
                        if (token != null) {
                          session.options.headers[HttpHeaders.authorizationHeader] =
                              ‘token $token’;
                        }
                        session.interceptors.requestLock.unlock();
                        return requestOptions;
                      },
                      onError: (e) => print(e.message),
                    ),
                  ]);
                  print(session.interceptors);
                }),
            RaisedButton(
                child: Text('Get Profile'),
                onPressed: () async {
                  session.get('/api/auth/').then((res) => print(res.data));
                }),
          ],
        ),
      ),
    );
  }
}

Console on clicking the log in button

Restarted application in 11,586ms.
flutter: starting
flutter: {key: 745c0a53112e61d54bea5ea725f7fa92e3a2cdbb}
flutter: [Instance of 'InterceptorsWrapper']

Console on the first time clicking the get profile button

flutter: Http status error [403]
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: DioError [DioErrorType.RESPONSE]: Http status error [403]
#0      DioMixin._request._errorInterceptorWrapper.<anonymous closure>.<anonymous closure>.<anonymous closure>
package:dio/src/dio.dart:870
#1      _rootRunUnary (dart:async/zone.dart:1198:47)
#2      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#3      _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
#4      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
#5      Future._propagateToListeners (dart:async/future_impl.dart:725:32)
#6      Future._completeWithValue (dart:async/future_impl.dart:529:5)
#7      Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
#8      _rootRun (dart:async/zone.dart:1190:13)
#9      _CustomZone.run (dart:async/zone.dart:1093:19)
#10     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
#11     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zon<…>

Console on subsequent times clicking the get profile button

flutter: {id: 3, username: tester, first_name: , last_name: , email: tester@tester.com}
Eli Per
  • 87
  • 2
  • 8
  • not sure is this helped ? https://stackoverflow.com/questions/56740793/using-interceptor-in-dio-for-flutter-to-refresh-token – John Joe Jan 21 '21 at 02:43
  • @JohnJoe Thanks but thats dealing with refreshing expired tokens. I'm getting fresh tokens with the login. – Eli Per Jan 21 '21 at 02:52

1 Answers1

2

5 more hours and finally figured out the problem.

session.options.headers[HttpHeaders.authorizationHeader] = 'token ' + token;

should be

requestOptions.headers[HttpHeaders.authorizationHeader] = 'token ' + token;
Eli Per
  • 87
  • 2
  • 8