How to make a plain text http (not https) request from Flutter
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);
Comments
-
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 over 4 yearsAnd you've tried
Response response = await get('http://10.0.2.2:3000');
? -
Miguel Ruivo over 4 yearsCan you show your
pubspec.yaml
? -
Hemanth Raj over 4 yearsplease change
Response response = await get('https://10.0.2.2:3000');
->Response response = await get('http://10.0.2.2:3000');
-
Suragch over 4 years@RichardHeap, good catch, I forgot to change the url to http. I updated the question.
-
Suragch over 4 years@miguelpruivo, I added my pubspec.yaml file.
-
Suragch over 4 years@HemanthRaj, I made the change and updated the question.
-
-
Suragch over 4 yearsWhat is the import for the
IOClient
? -
Suragch over 4 yearsFound it: stackoverflow.com/questions/54913772/…
-
Hussein Abdallah over 4 yearsplease mark the answer as correct if it solved your problem :)
-
Suragch over 4 yearsHave 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?