Flutter Web - http StreamedResponse 作为客户端接收 SSE

Goi*_*nas 9 dart flutter

拥有一个 Flutter 应用程序,在移动设备上运行时能够接收 SSE 文本/事件流事件,但在 Chrome Web 上运行时无法接收相同的 SSE 文本/事件流事件。

\n\n
import \'package:flutter/material.dart\';\nimport \'package:http/http.dart\' as http;\n\nvoid main() => runApp(MyApp());\n\nclass MyApp extends StatelessWidget {\n\n  http.Client _client;\n\n  MyApp() : super() {\n    print("Ctor called");\n    subscribe();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    print("building..");\n    return MaterialApp(\n      title: \'Flutter SSE\',\n      home: Scaffold(\n        appBar: AppBar(\n          title: Text(\'Receive SSE Events\'),\n        ),\n        body: Center(\n          child: Text(\'Ready for events..\'),\n        ),\n      ),\n    );\n  }\n\n  subscribe() async {\n    print("Subscribing..");\n    try {\n      _client = http.Client();\n\n      var request = new http.Request("GET", Uri.parse("http://192.168.1.11:8080/myserver/events"));\n      request.headers["Cache-Control"] = "no-cache";\n      request.headers["Accept"] = "text/event-stream";\n\n      Future<http.StreamedResponse> response = _client.send(request);\n      print("Subscribed!");\n\n      response.asStream().listen((streamedResponse) {\n        print("Received streamedResponse.statusCode:${streamedResponse.statusCode}");\n        streamedResponse.stream.listen((data) {\n          print("Received data:$data");\n        });\n      });\n    } catch(e) {\n      print("Caught $e");\n    }\n  }\n\n  unsubscribe() {\n    _client.close();\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在服务器端,我可以看到 flutter 应用程序始终订阅正常,因为我可以看到正在添加的接收器。服务器端始终将事件分派到 Sink,但 flutter 应用程序仅在作为移动应用程序运行时接收事件,而不是在作为 Chrome Web 应用程序运行时接收事件。

\n\n

是否有一个原因?这不是在浏览器和移动应用程序上运行的客户端 flutter 应用程序上接收 SSE 事件的正确方法吗?

\n\n

Flutter版本是1.10.6。Dart版本是2.5.1

\n\n

- - 更新 - -

\n\n

进行了 flutter 升级,现在运行如下:

\n\n
Flutter 1.10.15-pre.79 \xe2\x80\xa2 channel master \xe2\x80\xa2 https://github.com/flutter/flutter.git\nFramework \xe2\x80\xa2 revision 72d5c1c805 (2 hours ago) \xe2\x80\xa2 2019-10-11 03:58:43 -0400\nEngine \xe2\x80\xa2 revision 8dabfb90a1\nTools \xe2\x80\xa2 Dart 2.6.0 (build 2.6.0-dev.7.0 965b8cb1d8)\n
Run Code Online (Sandbox Code Playgroud)\n\n

但仍然遇到相同的行为,即作为移动应用程序运行时可以接收流式事件,但作为 Chrome Web 应用程序运行时无法接收流式事件。

\n\n

--- 更新 2 ---

\n\n

我一直读到,在 Web 浏览器上运行时可能会出现与 CORS 相关的问题,但据我所知,CORS 没有问题。服务器端的 CORS 已配置为接受所有来源(即"*"),配置为接受"GET"and"OPTIONS"方法,并配置为接受所有标头(即"*")。

\n\n

在Chrome浏览器中调试显示返回的响应是200,并且可以看到以下响应头:

\n\n
Access-Control-Allow-Origin: *\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\nContent-Type: text/event-stream;charset=UTF-8\nExpires: 0\nPragma: no-cache\ntransfer-encoding: chunked\nVary: Origin\nVary: Access-Control-Request-Method\nVary: Access-Control-Request-Headers\nX-Content-Type-Options: nosniff\nX-Frame-Options: DENY\nX-XSS-Protection: 1 ; mode=block\n
Run Code Online (Sandbox Code Playgroud)\n\n

不幸的是,我对 http 协议了解不够,所以我不知道上面的任何响应标头是否应该引起关注为什么无法在 Web 浏览器上接收事件流?

\n\n

附带说明一下,flutter/dart 代码最初是作为 angulardart/dart 代码编写的,并且该代码在 Chrome Web 浏览器上运行时能够很好地接收流式事件(因此假设 CORS 配置正确)。

\n\n

关于这个问题的任何帮助或指示将不胜感激。在 Chrome 上当前版本的 flutter web 中,即使是简单的“是”接收流式事件也是可能的,因此您一定在服务器端做错了什么。或者“不”,这在 Chrome 上当前版本的 flutter web 中不起作用,但最终它会/永远不会,等等。

\n

Oma*_*att 0

通常这些问题是由 CORS 被阻止引起的,但您共享的日志上的响应看起来不错。您可以尝试使用 html 渲染器运行 Web 应用程序,看看是否有效。这通常可以解决连接问题,值得一试。

flutter run -d chrome --web-renderer html
Run Code Online (Sandbox Code Playgroud)

Flutter Web 上的 Streams 似乎过早地被丢弃,并在此GitHub 问题单上对其进行了跟踪。您还可以尝试切换到dev频道,看看是否可以解决问题。