Eli Per
Eli Per

Reputation: 97

Dio Interceptor not working on first request in same callback, only subsequent calls

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: [email protected]}

Upvotes: 2

Views: 4027

Answers (1)

Eli Per
Eli Per

Reputation: 97

5 more hours and finally figured out the problem.

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

should be

requestOptions.headers[HttpHeaders.authorizationHeader] = 'token ' + token;

Upvotes: 3

Related Questions