cfug/dio

DIo not working while adding extras in requestOptions with path in Dio singleton

parmeetmaster opened this issue · 3 comments

Package

dio

Version

dio: ^5.4.3+1

Operating-System

Android

Adapter

Default Dio

Output of flutter doctor -v

I/flutter (28646): ╔╣ Request ║ POST 
I/flutter (28646): ║  https://stgapp.***.com/sales-**-stg/smaPropertyBased/0
I/flutter (28646): ╚══════════════════════════════════════════════════════════════════════════════════════════╝
I/flutter (28646): ╔ Headers 
I/flutter (28646): ╟ content-type: application/json
I/flutter (28646): ╟ clientId: SMP100475
I/flutter (28646): ╟ latitude: 22.6388417
I/flutter (28646): ╟ Longitude: 72.082512
I/flutter (28646): ╟ token: 
I/flutter (28646): ║ eyJhbGciOiJSUzI1NiIsImkiOkpXVCJ9.eyJzdWIiOiJTTVAxMDA2NDkiLCJlIjoicGFybWVld
I/flutter (28646): ║ C5zaW5naEBzcGljZW1vbmV5LmNvbSIsImlU1BJQ0VfaW1wYWN0IiwiZXhwIjoxNzE3MjM0NTY4LCJtIjo
I/flutter (28646): ║ iOTg3MTkxNzUxNSIsImlhdCI6MTcxNzIzNDI2OH0.XD7Ll8vwL5LtJcN_RB8y_8UeCh3jEl9c5a-fAmgEA8JJwQLFj
I/flutter (28646): ║ _lOmVD0P1n-ViEUcKOBjDZN_77s_bfjiYZYLA2xhkNueH83ttBLjkMckxWH7cNYVYqlJHb-S3_ML1F166Y2cv5EEvu
I/flutter (28646): ║ yp0n_4QVQ95aXE24nJs4HRR_b9vArfsnTc-Nb3dVOTT35mmgd5m2UR8ENUj4MT9yj5FD3TxNZQHAOSzJ8AwOCZwWqR
I/flutter (28646): ║ HgFUz3C9usocEX8Is--amAvWKewPn9kfUobjC4kKaUSSYFhkbOdGrVHPBBOXiIRPbBivMwLjf1VD2XZjSyfE59UPh_
I/flutter (28646): ║ EtXM5rZLb7K9ExiR4BbZvHA
I/flutter (28646): ╟ r-token: ****
I/flutter (28646): ║ eyJhbGciOiJSUzAxMDA2NDkiLCJlIjoicGFybWVld
I/flutter (28646): ║ C5zaW5naEBzcGljZW1vbmV5LmNvbSIsImlzcyI6IlJfU1BJQ0VfaW1wYWN0IiwiZXhwIjoxNzI1MDEwMjY4LCJtIjo
I/flutter (28646): ║ iOTg3MTkxNzUxNSIsImlhdCI6MTcxNzIzNDI2OH0.GXtiCiDHO7xF898zRhYVhMCC5grOyfYjotjhzQyS_0-6-sSI8
I/flutter (28646): ║ H_X2M1KhlpJbUJ7xJ-ByFV3YsU4ht14E7Sq99yJjx13JvxY348jQPseHaljrmnxg_ZgbYM-gxTTiAeAQBPvicsACcM
I/flutter (28646): ║ 0E-JmAN2KdPBwrOsl53QdZaKb4A0ahvLuQqDsxRLGvkabe6djQoZEGDYg3XOmgF8Ulq19_s-oj7JWsb6UFgJuIHDQZ
I/flutter (28646): ║ Z5OdNIiUWKsb21GangDdLuHX83H9uf4aFEW3LPhHao_l3uUXV5pyZN-WjdaICGgzzFnpOErzTz_w2uvzOi8D5Cal0T
I/flutter (28646): ║ -tSeT7gsFY8i_R7f4C2cCXQ
I/flutter (28646): ╟ appVer: 2.0.12
I/flutter (28646): ╟ userRole: Cluster 
I/flutter (28646): ╟ lang: en
I/flutter (28646): ╟ contentType: application/json
I/flutter (28646): ╟ responseType: ResponseType.json
I/flutter (28646): ╟ followRedirects: true
I/flutter (28646): ╟ connectTimeout: 0:00:30.000000
I/flutter (28646): ╟ receiveTimeout: null
I/flutter (28646): ╚══════════════════════════════════════════════════════════════════════════════════════════╝
I/flutter (28646): ╔ Extras 
I/flutter (28646): ╟ date: 2024-06-01 15:31:34.913083
I/flutter (28646): ╚══════════════════════════════════════════════════════════════════════════════════════════╝
I/flutter (28646): ╔ Body 
I/flutter (28646): ╟ cluster: 
I/flutter (28646): ╟ distId: null
I/flutter (28646): ╟ requestType: monthly
I/flutter (28646): ╟ pincode: 
I/flutter (28646): ╟ filterBy: 
I/flutter (28646): ╟ totalSma: 
I/flutter (28646): ╚══════════════════════════════════════════════════════════════════════════════════════════╝
I/flutter (28646): ║ {, cluster: , distId:
I/flutter (28646): ║  null, requestType: monthly, pincode: , filterBy: , totalSma: }
I/flutter (28646): ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter (28646): │ #0   mstrings.printwtf (package:spice_impact_new/utils/logs.dart:12:29)
I/flutter (28646): │ #1   UserExperiaDioInterceptor.onRequest (package:spice_impact_new/data/datasources/network/modules/user_experia_dio_interceptor.dart:16:50)
I/flutter (28646): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter (28646): │ 👾 @#experia request /smaPropertyBased/0
I/flutter (28646): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter (28646): 
I/flutter (28646): ╔╣ DioError ║ DioExceptionType.unknown
I/flutter (28646): ║  null
I/flutter (28646): ╚══════════════════════════════════════════════════════════════════════════════════════════╝
I/flutter (28646): ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter (28646): │ #0   mstrings.printwtf (package:spice_impact_new/utils/logs.dart:12:29)
I/flutter (28646): │ #1   UserExperiaDioInterceptor.onError (package:spice_impact_new/data/datasources/network/modules/user_experia_dio_interceptor.dart:25:64)
I/flutter (28646): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter (28646): │ 👾 @#experia error {date: 2024-06-01 15:31:34.913083}
I/flutter (28646): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/TRuntime.CctTransportBackend(28646): Making request to: https://firebaselogging-pa.googleapis.com/v1/firelog/legacy/batchlog
I/TRuntime.CctTransportBackend(28646): Status Code: 200
I/UserExperiorLogs(28646): idle
I/UserExperiorLogs(28646): R -- P
I/UserExperiorLogs(28646): R -- R

Dart Version

dio: ^5.4.3+1

Steps to Reproduce

I am adding extras in dio.post
Future<d.Response> post(String path, Map<String, dynamic> data,
{String? baseUrl = null, d.CancelToken? cancelToken,UserExperiaModel? userExperiaModel}) async {
if (dio == null) {
await _initalised();
}

d.Options? requestOptions;

if(userExperiaModel!=null){

  requestOptions=d.Options(
      extra:{"date":DateTime.now()});
}

dio!.options.contentType = "application/json";

d.Response response =
await dio!.post(path ,options: requestOptions, data: data, cancelToken: cancelToken);
return response;

}

Expected Result

Result should be json response that i use to sent data.

Actual Result

image

I am getting null while adding extras without that it works fine

extra does not involved with any computation of the request. Could you attach a minimal reproducible example?

/*
 * Copyright © 2023, This code is developed by
 *  Under work enviorment of tata money.Sharing and distributor source code outside organisaton is prohibited.
 */

import 'dart:io';

import 'package:colorize/colorize.dart';
import 'package:dio/dio.dart' as d;
import 'package:dio/dio.dart';
import 'package:dio_smart_retry/dio_smart_retry.dart';
import 'package:file_support/file_support.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import 'package:tata_impact_new/data/datasources/local/services/file_service.dart';
import 'package:tata_impact_new/data/datasources/network/modules/enviorment_module.dart';
import 'package:tata_impact_new/data/datasources/network/modules/user_experia_dio_interceptor.dart';
import 'package:tata_impact_new/data/datasources/network/services/user_experior_service.dart';
import 'package:tata_impact_new/data/datasources/network/utils/dio_performance_adapter.dart';
import 'package:tata_impact_new/data/datasources/network/utils/handle_response.dart';
import 'package:tata_impact_new/data/models/user_experia_model.dart';
import 'package:tata_impact_new/data/repositories/core/i_core_data_repo.dart';
import 'package:tata_impact_new/data/repositories/firebase_analytics_events/i_firebase_analytics_event.dart';
import 'package:tata_impact_new/dependency_injection/inject.dart';
import 'package:tata_impact_new/utils/utils.dart';
import 'package:uuid/uuid.dart';

import '../../../../utils/FLocation.dart';
import '../../local/services/kv_storage_service.dart';
import 'package:uuid/uuid.dart' as uuid;

/*---------------------------------Interceptors ---------------------------*/
class MasterInterceptor extends d.Interceptor {
  final showToken = true;

  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    MEnviorment enviorment = getIt<MEnviorment>();
    String? _token = await getIt<KVStorageService>().accessToken;
    String? _rToken = await getIt<KVStorageService>().refreshToken;



    options.connectTimeout = const Duration(seconds: 30);

    if (_token != null || _rToken != null) {
      _token!.printinfo;
      _rToken!.printinfo;
    }
    if (showToken && (enviorment.env == ENVIORMENT.debug)) {
      color("TOKEN: ${_token}\n",
          front: Styles.BG_GREEN,
          isBold: true,
          isItalic: false,
          isUnderline: false);
      color("R-TOKEN: ${_rToken}\n",
          front: Styles.BG_BLUE,
          isBold: true,
          isItalic: false,
          isUnderline: false);
    }
    /*   String lat = kReleaseMode
        ? Flocation.instance.locationData?.latitude.toString() ?? ""
        : "25.98217";
    String long = kReleaseMode
        ? Flocation.instance.locationData?.longitude.toString() ?? ""
        : "80.10131";*/

    String lat = Flocation.instance.locationData?.latitude.toString() ?? "";
    String long = Flocation.instance.locationData?.longitude.toString() ?? "";

    //package
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    String _version = packageInfo.version;
    // clientId
    String role = "";
    try {
      role = getIt<ICoreDataRepo>().coreData.role;
    } catch (e) {
      role = "";
    }

    options.headers.addAll({
      'clientId': getIt<ICoreDataRepo>().clientId ?? "",
      'latitude': lat ?? "",
      'Longitude': long ?? "",
      'token': _token ?? "",
      'r-token': _rToken ?? "",
      'appVer': _version,
      'userRole': role,

      'lang': "en",
      'merchant': "IMPACT",
    });
    print("sending data ${options.headers.toString()}");
    return super.onRequest(options, handler); // its required to add
  }

  @override
  void onError(d.DioException err, ErrorInterceptorHandler handler) {
    if (err.response!.statusCode == 403) {
      print("seassion expire");
    } else if (err.response!.statusCode == 400) {
      getIt<IFireBaseAnalyticsEventRepo>().apiRecord400Error(
          (err.response?.requestOptions.baseUrl ?? "") +
              (err.response?.requestOptions.path ?? ""));
    }
    return handler.next(err);
  }

  @override
  void onResponse(
      d.Response response, ResponseInterceptorHandler handler) async {


    if (response.statusCode == 400) {
      getIt<IFireBaseAnalyticsEventRepo>().apiRecord400Error(
          (response.requestOptions.baseUrl ?? "") +
              (response.requestOptions.path ?? ""));
    }

  return  super.onResponse(response, handler);
  }
}

class AuthenticationInterceptor extends d.Interceptor {
  final showToken = true;

  // this is not staging ot prod url its other Url that is using for authentication
  static const LOGIN_API_ENDPOINT =
      "https://dl.tatamoney.com/auth/gouth/impact/app";
  static const LOGIN_WITH_EMAIL_API_ENDPOINT =
      "https://dl.tatamoney.com/auth/loginStore/impact/app";
  static const LOGIN_WITH_STAGING_API_ENDPOINT =
      "https://stgapp.tatamoney.com/impact-auth/gouth/impact/app";

  @override
  void onResponse(
      d.Response response, ResponseInterceptorHandler handler) async {
    if (((response.requestOptions.baseUrl + response.requestOptions.path)
                .contains(LOGIN_API_ENDPOINT) ||
            (response.requestOptions.baseUrl + response.requestOptions.path)
                .contains(LOGIN_WITH_EMAIL_API_ENDPOINT)) ||
        (response.requestOptions.baseUrl + response.requestOptions.path)
                .contains(LOGIN_WITH_STAGING_API_ENDPOINT) &&
            response.statusCode == 200) {
      String _token = response.headers["token"]?.first ?? "null";
      String _rToken = response.headers["r-token"]?.first ?? "null";
      await getIt<KVStorageService>().setAccessToken(_token);
      await getIt<KVStorageService>().setRefreshToken(_rToken);
      //await getIt<AuthInterceptor>().initialize();
    }
    return super.onResponse(response, handler);
  }
}

/*Client logic*/

class DioClient with HandleApiResultMixin {
  late KVStorageService _kvStorageService;
  d.Dio? dio;

  String baseUrl;
  String stagingUrl;

  DioClient({required this.baseUrl, required this.stagingUrl}) {
    _initalised();
  }

  _initalised() async {
    MEnviorment menviorment = getIt<MEnviorment>();

    if (menviorment.env == ENVIORMENT.prod) {
      baseUrl = baseUrl;
    } else {
      baseUrl = stagingUrl;
    }
    dio = d.Dio();
    dio!.options.baseUrl = baseUrl;
    dio!.interceptors.addAll(
      [
   /*     RetryInterceptor(
          dio: dio!,
          logPrint: print, // specify log function (optional)
          retries: 3, // retry count (optional)
          retryDelays: const [
            Duration(seconds: 5),
            Duration(seconds: 10),
            Duration(seconds: 30),
          ],
        ),*/
        UserExperiaDioInterceptor(),
        AuthenticationInterceptor(),
        MasterInterceptor(),
        DioFirebasePerformanceInterceptor(),
        PrettyDioLogger(
          requestHeader: true,
          requestBody: true,
          error: true,
          responseBody: true,
          responseHeader: false,
          compact: false,
        ),

      ],
    );
  }

  Future<d.Response> get(String path, Map<String, dynamic> queryparms,
      {d.CancelToken? cancelToken,UserExperiaModel? userExperiaModel}) async {
    if (dio == null) {
      await _initalised();
    }




    d.Response response = await dio!
        .get(path, queryParameters: queryparms, cancelToken: cancelToken);

    return response;
  }

@AlexV525 pls focus this i am adding here extras.

  Future<d.Response> post(String path, Map<String, dynamic> data,
      {String? baseUrl = null, d.CancelToken? cancelToken,UserExperiaModel? userExperiaModel}) async {
    if (dio == null) {
      await _initalised();
    }


    if(userExperiaModel!=null){

      userExperiaModel=userExperiaModel.copyWith(properties: userExperiaModel.properties.copyWith(requestBody: data.toString()));
     dio!.options.copyWith(extra: userExperiaModel.toJson());
    }


    dio!.options.contentType = "application/json";

    d.Response response =
    await dio!.post(path , data: data, cancelToken: cancelToken);
    return response;
  }

  Future<d.Response> postWithQueryParameters(
      String path, Map<String, dynamic> data,
      {Map<String, dynamic>? queryParams}) async {
    if (dio == null) {
      await _initalised();
    }
    dio!.options.contentType = "application/json";
    d.Response response =
        await dio!.post(path, queryParameters: queryParams, data: data);
    return response;
  }



  Future<d.Response> postFormDataWithQueryParameters(
      String path, Map<String, dynamic> data,
      {Map<String, dynamic>? queryParams}) async {
    dio!.options.contentType = "multipart/form-data";

    if (dio == null) {
      await _initalised();
    }
    return await dio!.post(path,
        queryParameters: queryParams, data: d.FormData.fromMap(data));
  }

  //post  raw data
  Future<d.Response> postRawDataWithQueryParameters(String path,
      {required Map<String, dynamic> queryParams,
      required Map<String, dynamic> data}) async {
    if (dio == null) {
      await _initalised();
    }
    return await dio!.post(path, queryParameters: queryParams, data: data);
  }

// post form data
  Future<d.Response> postFormData(
      String path, Map<String, dynamic> data) async {
    dio!.options.contentType = "multipart/form-data";

    if (dio == null) {
      await _initalised();
    }

    return await dio!.post(
      path,
      data: d.FormData.fromMap(data),
    );
  }

  /// used to take compress image form multipart
  Future<d.MultipartFile> getMultiPartImage(File file) async {
    "FILE PATH: ${file.path}".printinfo;
    File? compressFile = await FileSupport().compressImage(file, quality: 50);
    final d.MultipartFile multipart = await d.MultipartFile.fromFile(file.path);
    return multipart;
  }

  Future<d.MultipartFile> getMultiPartImageCompressed(File file) async {
    "FILE PATH: ${file.path}".printinfo;
    File? compressFile = await getIt<FileService>().getCompressImage(file);
    d.MultipartFile multipart =
        await d.MultipartFile.fromFile(compressFile.path);
    return multipart;
  }

  Future<d.MultipartFile> getMultiPart(File file) async {
    "FILE PATH: ${file.path}".printinfo;
    d.MultipartFile multipart = await d.MultipartFile.fromFile(file.path);
    return multipart;
  }

  Future<DioClient> init() async {
    await _initalised();
    return this;
  }
}

Your code involves too many unrelated implementations and they are also inaccessible to us. Please make a minimal example to reproduce your case.