Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter error in Dio https request. HandshakeException: Handshake error in client OS Error: (TLSV1_ALERT_DECODE_ERROR(tls_record.cc:594))

I am trying to send a https request from flutter with following function:

Future<void> sendOTP(PhoneNumber phoneNumber) async {
    try {
      final String url = 'https://127.0.0.1:5432/api/send_otp';

      final response = await _dio.post(
        url,
        data: {'number': 1234567890},
        options: Options(
          headers: {
            'Content-Type': 'application/json',
          },
        ),
      );

      if (response.statusCode != 200) {
        throw Exception("Failed to send OTP: ${response.statusCode}");
      }
    } on DioError catch (e) {
      throw Exception("Failed to send OTP: ${e.error.toString()}");
    }
  }

To enable ssl certificate I have added following code in my main method:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  ByteData data = await PlatformAssetBundle().load('asset/certificate/certificate.pem');
  SecurityContext.defaultContext
      .setTrustedCertificatesBytes(data.buffer.asUint8List());
  runApp(const MyApp());
}

I have downloaded the certificate.pem file from https://letsencrypt.org/certs/lets-encrypt-r3.pem.

When I am sending the request using thunderclient or postman with the certificate, it works but from the flutter app it throws following error:

Error: HandshakeException: Handshake error in client (OS Error:
    TLSV1_ALERT_DECODE_ERROR(tls_record.cc:594))

For server, I am using actix-web with rustls - if relevant. Please suggest how do I fix the same?

like image 686
Rusty Avatar asked Feb 03 '26 21:02

Rusty


2 Answers

after a research I finally found the solution for this problem. Basically you have to add the following code when creating a Dio instance:

class DioSingleton {
  static final baseOptions = BaseOptions(
    baseUrl: "https://10.0.2.2:7027/api/",
  );

  static Dio createInstance() {
    var dio = Dio(baseOptions);
    dio.httpClientAdapter = IOHttpClientAdapter(
      createHttpClient: () {
        final client = HttpClient();
        client.badCertificateCallback = (cert, host, port) => true;
        return client;
      },
    );
    return dio;
  }
}

Also, you dont need to configure the Android emulator to use proxy or any different configuration. Just use this "as is" and everything will work. Remember to use the address 10.0.2.2 if you have a localhost api running on your machine. In my case, I have an .net6 API running in localhost. Please mark this as the accepeted answer if this solved your problem.

like image 64
delta2_ Avatar answered Feb 05 '26 12:02

delta2_


Try this:

final Dio client = Dio();

client.httpClientAdapter = IOHttpClientAdapter(
  createHttpClient: () {
    return HttpClient()..badCertificateCallback = (_, __, ___) => true;
  },
);
like image 39
Anas Esh Avatar answered Feb 05 '26 12:02

Anas Esh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!