node.js - 如何从 Flutter 发出纯文本 http(而非 https)请求

标签 node.js http https dart flutter

出于测试目的,我想禁用加密,以便我可以使用 http 而不是 https 将我的 Flutter 应用程序连接到在本地主机上运行的服务器。 I've already been able to do it with https ,但我遇到了 http 崩溃,因为默认情况下 Android 和 iOS 都不允许纯文本请求。

这是我的错误:

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)

在 Android 中,我可以通过向 list 添加设置来禁用加密:

android:usesCleartextTraffic="true"

在 iOS 中,我可以通过向 Info.plist 添加设置来执行相同的操作:

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

但我不知道如何在 Flutter 中做到这一点。

补充代码

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 应用程序.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}/`);
});

使用 Android 9 模拟器 (API 28) 进行测试。

更新 1:

我尝试将 android:usesCleartextTraffic="true" 添加到 Flutter 中的 Android list ,但这并没有阻止 Dart 错误。

更新 2:

我在我的代码中使用 https 而不是 http。我更新了上面的内容并更改为新的错误消息。

更新 3

嗯,Flutter 有一个更新 (1.2.2),我升级了。然后我重新启动了 Android Studio。现在,仅使用上面的代码,它就可以正常工作了。我不知道是什么导致了异常。难道Flutter不需要https?

最佳答案

创建一个新的httpclient并禁用证书检查

HttpClient httpClient = new HttpClient()
..badCertificateCallback =
    ((X509Certificate cert, String host, int port) => true);
IOClient ioClient = new IOClient(httpClient);
ioClient.get(url);

关于node.js - 如何从 Flutter 发出纯文本 http(而非 https)请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54894936/

相关文章:

rest - Web 应用程序中长时间运行的操作

ruby - HTTPS请求错误: undefined method `set_body_internal'

ruby-on-rails - 必须手动将 'https://' 添加到 url

php - 让 SSL 在 Xampp 中工作 - 访问禁止错误

c - 获取在线通知的最简单方法

javascript - 基本范围问题(javascript 和 Node)

node.js - 将8kHz mulaw转换为PCM 16kHz

node.js - 如何检查网络流量并获取资源请求的URL?

node.js - 如何在环回中获取当前工作人员 ID?

javascript - 如何在AJAX中获取复选框值