Santosh Kumar
Santosh Kumar

Reputation: 196

How to resend a multipart request?

I am retrying my API call if it gets an status code = 401, but when it's called the second time,I am getting the following exception:

[![Bad state][1]][1]

This is the code for retrying the multipart request. I had used [http_interceptor][2] package for retrying API calls interceptor.dart:

    class AuthorizationInterceptor extends InterceptorContract {
      @override
      Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
        final prefs = await SharedPreferences.getInstance();
    
        final extractData =
            json.decode(prefs.getString('userData')!) as Map<String, dynamic>;
    
        final Map<String, String> headers = Map.from(request.headers);
        headers['Authorization'] = await extractData['accessToken'];
        print(
            'this is from AuthorizationInterceptor: ${extractData['accessToken']}');
        // TODO: implement interceptRequest
    
        return request.copyWith(
          headers: headers,
        );
      }

retry.dart:


    class ExpiredTokenRetryPolicy extends RetryPolicy {
      BuildContext context;
      ExpiredTokenRetryPolicy(this.context);
      @override
      // TODO: implement maxRetryAttempts
      int get maxRetryAttempts => 2;
    
      @override
      Future<bool> shouldAttemptRetryOnResponse(BaseResponse response) async {
        if (response.statusCode == 401) {
          print('retry token started');
          //perform token refresh,get the new token and update it in the secure storage
    
          await Provider.of<Auth>(context, listen: false).restoreAccessToken();
          return true;
        }
        return false;
      }

I am using interceptors in my widget following is my code where I am using interceptors and using retry policy


    @override
      Widget build(BuildContext context) {
        var flutterFunctions = Provider.of<FlutterFunctions>(context);
    
        // print('this is from insert package${token.token}');
        ApiCalls repository = ApiCalls(
          client: InterceptedClient.build(
            retryPolicy: ExpiredTokenRetryPolicy(context),
            interceptors: [
              AuthorizationInterceptor(),
            ],
          ),
        );

following is my restore access token method

    Future<void> restoreAccessToken() async {
        print('restoreAccessToken started');
    
        //print(token);
        final url = '${Ninecabsapi().urlHost}${Ninecabsapi().login}/$sessionId';
    
        var response = await http.patch(
          Uri.parse(url),
          headers: {
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': accessToken!
          },
          body: json.encode(
            {"refresh_token": refreshtoken},
          ),
        );
        var userDetails = json.decode(response.body);
    
        if (response.statusCode == 401) {
          print(userDetails['messages']);
        }
    
        sessionId = userDetails['data']['session_id'];
        accessToken = userDetails['data']['access_token'];
        accessTokenExpiryDate = DateTime.now().add(
          Duration(seconds: userDetails['data']['access_token_expiry']),
        );
        refreshToken = userDetails['data']['refresh_token'];
        refreshTokenExpiryDate = DateTime.now().add(
          Duration(seconds: userDetails['data']['refresh_token_expiry']),
        );
        final userData = json.encode({
          'sessionId': sessionId,
          'refreshToken': refreshToken,
          'refreshExpiry': refreshTokenExpiryDate!.toIso8601String(),
          'accessToken': accessToken,
          'accessTokenExpiry': accessTokenExpiryDate!.toIso8601String()
        });
        //print(userDetails);
    
        notifyListeners();
        final prefs = await SharedPreferences.getInstance();
    
        prefs.setString('userData', userData);
        print("this is from restoreAcessToken :$userDetails");
        final extractData =
            json.decode(prefs.getString('userData')!) as Map<String, dynamic>;
        print('restore access token: ${extractData['accessToken']}');
        reset();
      }


  [1]: https://i.sstatic.net/0i0O3.png
  [2]: https://pub.dev/packages/http_interceptor

Upvotes: -3

Views: 632

Answers (1)

Moemen
Moemen

Reputation: 404

As a rule. You must NOT write using the same Stream/MultipartFile more than once. If you need to retry sending to the same destination, you have to use a new MultipartFile each time you retry.

Upvotes: -1

Related Questions