How to make a plain text http (not https) request from Flutter

6,830

create a new httpclient and disable certificate checking

HttpClient httpClient = new HttpClient()
..badCertificateCallback =
    ((X509Certificate cert, String host, int port) => true);
IOClient ioClient = new IOClient(httpClient);
ioClient.get(url);
Share:
6,830
Suragch
Author by

Suragch

Read my story here: Programming was my god

Updated on December 09, 2022

Comments

  • Suragch
    Suragch 11 months

    For testing purposes I would like to disable encryption so that I can connect my Flutter app to a server running on my localhost using http, not https. I've already been able to do it with https, but I get a crash for http because both Android and iOS do not allow plain text requests by default.

    Here is my error:

    E/flutter ( 9119): [ERROR:flutter/shell/common/shell.cc(186)] Dart Error: Unhandled exception:
    E/flutter ( 9119): SocketException: OS Error: Connection refused, errno = 111, address = 10.0.2.2, port = 40738
    E/flutter ( 9119): #0      IOClient.send (package:http/src/io_client.dart:33:23)
    E/flutter ( 9119): <asynchronous suspension>
    E/flutter ( 9119): #1      BaseClient._sendUnstreamed (package:http/src/base_client.dart:169:38)
    E/flutter ( 9119): <asynchronous suspension>
    E/flutter ( 9119): #2      BaseClient.get (package:http/src/base_client.dart:32:7)
    E/flutter ( 9119): #3      get.<anonymous closure> (package:http/http.dart:46:36)
    E/flutter ( 9119): #4      _withClient (package:http/http.dart:166:20)
    E/flutter ( 9119): <asynchronous suspension>
    E/flutter ( 9119): #5      get (package:http/http.dart:46:5)
    E/flutter ( 9119): #6      _makeGetRequest (package:flutter_client/main.dart:64:29)
    E/flutter ( 9119): <asynchronous suspension>
    E/flutter ( 9119): #7      BodyWidgetState.build.<anonymous closure> (package:flutter_client/main.dart:48:19)
    E/flutter ( 9119): #8      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:507:14)
    E/flutter ( 9119): #9      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:562:30)
    E/flutter ( 9119): #10     GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
    E/flutter ( 9119): #11     TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
    E/flutter ( 9119): #12     TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:175:7)
    E/flutter ( 9119): #13     PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:315:9)
    E/flutter ( 9119): #14     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
    E/flutter ( 9119): #15     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)
    E/flutter ( 9119): #16     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:180:19)
    E/flutter ( 9119): #17     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:158:22)
    E/flutter ( 9119): #18     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:138:7)
    E/flutter ( 9119): #19     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:101:7)
    E/flutter ( 9119): #20     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:85:7)
    E/flutter ( 9119): #21     _invoke1 (dart:ui/hooks.dart:173:13)
    E/flutter ( 9119): #22     _dispatchPointerDataPacket (dart:ui/hooks.dart:127:5)
    

    In Android I can disable encryption by adding a setting to the manifest:

    android:usesCleartextTraffic="true"
    

    In iOS I can do the same by adding a setting to Info.plist:

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    

    But I don't know how to do that in Flutter.

    Supplemental code

    Flutter main.dart

    import 'package:flutter/material.dart';
    import 'package:http/http.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Node server demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            appBar: AppBar(title: Text('Flutter Client')),
            body: BodyWidget(),
          ),
        );
      }
    }
    
    class BodyWidget extends StatefulWidget {
      @override
      BodyWidgetState createState() {
        return new BodyWidgetState();
      }
    }
    
    class BodyWidgetState extends State<BodyWidget> {
      String serverResponse = 'Server response';
    
      @override
      Widget build(BuildContext context) {
    
        return Padding(
          padding: const EdgeInsets.all(32.0),
          child: Align(
            alignment: Alignment.topCenter,
            child: SizedBox(
              width: 200,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  RaisedButton(
                    child: Text('Send request to server'),
                    onPressed: () {
                      _makeGetRequest();
                    },
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(serverResponse),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    _makeGetRequest() async {
      Response response = await get('http://10.0.2.2:3000');
    
      int statusCode = response.statusCode;
      Map<String, String> headers = response.headers;
      String contentType = headers['content-type'];
      String json = response.body;
    
      print(statusCode);
      print(headers);
      print(contentType);
      print(json);
    }
    

    Flutter pubspec.yaml

    name: flutter_client
    description: Flutter client to test Node.js server
    version: 1.0.0+1
    
    environment:
      sdk: ">=2.1.0 <3.0.0"
    
    dependencies:
      flutter:
        sdk: flutter
      http: ^0.12.0+1
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
    
    flutter:
      uses-material-design: true
    

    Node.js app.js

    const http = require('http');
    
    const hostname = '127.0.0.1';
    const port = 3000;
    
    const server = http.createServer((req, res) => {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/plain');
      res.end('Hello World\n');
    });
    
    server.listen(port, hostname, () => {
      console.log(`Server running at http://${hostname}:${port}/`);
    });
    

    Testing with Android 9 emulator (API 28).

    Update 1:

    I tried adding android:usesCleartextTraffic="true" to the Android manifest in Flutter, but that didn't prevent the Dart error.

    Update 2:

    I was using https in my code rather than http. I updated that above and also changed to the new error message.

    Update 3

    Hmm, Flutter had an update (1.2.2) and I upgraded. Then I restarted Android Studio. And now it is working without any errors just with the code above. I don't know what was causing the exception. Could it be that Flutter doesn't require https?

    • Richard Heap
      Richard Heap over 4 years
      And you've tried Response response = await get('http://10.0.2.2:3000');?
    • Miguel Ruivo
      Miguel Ruivo over 4 years
      Can you show your pubspec.yaml?
    • Hemanth Raj
      Hemanth Raj over 4 years
      please change Response response = await get('https://10.0.2.2:3000'); -> Response response = await get('http://10.0.2.2:3000');
    • Suragch
      Suragch over 4 years
      @RichardHeap, good catch, I forgot to change the url to http. I updated the question.
    • Suragch
      Suragch over 4 years
      @miguelpruivo, I added my pubspec.yaml file.
    • Suragch
      Suragch over 4 years
      @HemanthRaj, I made the change and updated the question.
  • Suragch
    Suragch over 4 years
    What is the import for the IOClient?
  • Suragch
    Suragch over 4 years
  • Hussein Abdallah
    Hussein Abdallah over 4 years
    please mark the answer as correct if it solved your problem :)
  • Suragch
    Suragch over 4 years
    Have you tried it with and without this code? I don't know why but I stopped getting the error without using your solution. I just used the code in my question. So does Flutter not require https like Android and iOS do?