Flutter Web 集成测试 CORS XMLHttpRequest 错误

标签 flutter http testing cors flutter-web

我正在本地为 Web 运行 Flutter 集成测试。这是一个示例集成测试,其中我唯一要做的就是按下一个按钮,ping https://google.com ,然后在收到响应后完成。
当我在本地运行此集成测试时,我收到 XMLHttpRequest错误。这可能是 CORS 错误,但我不确定是不是这种情况。
如何在集成测试中为不属于我的网站发出 HTTP 请求?
flutter 版本:

Flutter 2.2.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b22742018b (12 days ago) • 2021-05-14 19:12:57 -0700
Engine • revision a9d88a4d18
Tools • Dart 2.13.0
错误:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞═════════════════
The following ClientException was thrown running a test:
XMLHttpRequest error.

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 909:28 get current
...

最佳答案

为什么会发生这种情况?
正如您所说,您正在尝试 ping,即发出 HTTP 请求到 https://www.google.com在 Web 集成测试中。
在网络上运行任何东西时,网络安全 适用。在 Web 安全模型中,安全性由浏览器引擎使用 Same-origin policy 强制执行。 ,这主要涉及浏览器引擎阻止前端 JavaScript 访问来自跨源请求的响应。但是可以通过使用 Cross-Origin Resource Sharing (CORS) 来克服这种阻塞。 ,这是服务器告诉浏览器他们明确允许跨域访问的一种方式。
这通常使用 Access-Control-Allow-Origin header 来完成。 .
由于您的集成测试将始终在 上运行localhost ,任何外部 HTTP 请求都将是跨域的。
CORS 示例
让我们检查一下 https://www.google.com ,这是你的例子:
google.com GET request
如你所见,你看不到它。对了,没有Access-Control-Allow-Origingoogle.com 发送的响应头.
→ 这意味着根据网络安全,您是 不允许提出此请求 来自不同的域(跨域)。
它与Web集成测试有什么关系吗?
现在,问题可能会出现“为什么相同的集成测试适用于移动设备”。
是的,这是一个很好的问题,答案很简单。 CORS 策略只存在于网络上,即它们实际上只存在 浏览器内部 .这是因为任何人都可以在网络上注入(inject)任何代码(基本上)。然而,在移动设备上,请求是安全的,这就是为什么你可以提出任何你想要的请求——在网络上,你不能。

Flutter Web 集成测试将在 Chrome 实例中运行,此 有道理 .集成测试的重点是模拟真实行为,即查看组件是否协同工作以及 Flutter 的 integration_test ing(在某种程度上更接近于自动化 e2e 测试),这意味着测试应用程序是否能在网络平台上成功运行。
→ 想一想,这种方式集成测试也是最有意义的,因为同样的请求会也失败 在真正的网络应用程序中。
和 Flutter 有关系吗?
, 绝对不!其实没有框架,没办法避免这种情况,因为它是 意向 . Web 平台一般都有这些安全策略,您将不得不处理它们。
这意味着 没有网络应用程序 可以向 https://www.google.com 发出 HTTP 请求(截至 2021 年 5 月 27 日)除非它实际上在同一个域上运行。

我们可以使用 Chrome 的 JS 控制台和 ping https://www.google.com 快速可视化这一点。从控制台,一次是在随机网站上,一次是在 Chrome 上。
Pinging google.com
如您所见,请求甚至在 JS 控制台中失败。您可能认为控制台具有特权,但即使在那里请求也会失败 除非 你在同一个起源(左侧)。
请注意,错误消息中指定了不同的策略/ header 。这将根据所使用的浏览器而有所不同,并且与争论/不理解无关。
解决方案
既然我们已经确定这实际上是预期的行为,那么我们如何正确地做到这一点,我们如何使其发挥作用?
使用正确的资源
您的测试失败,因为它 应该失败。在 Web 上,您无法访问所需的域。但是,如果您使用了一个实际上允许它的方法呢?
当然,有许多站点实际上确实允许 CORS,即允许从外部源访问。在这里你可以看到 https://i.imgur.com/MQdD3lg.png 的响应头:
i.imgur request
Imgur 提供用于共享的图像,因此他们合乎逻辑地希望允许将这些图像嵌入到任何网站或 Web 应用程序中。这就是为什么你可以看到:

access-control-allow-origin: *
这意味着可以从 请求图像任何地方 ,来自任何域。
→ 我建议您改用它来 ping 集成测试 ;)
这不是错误
为了强调这是 100% 的预期行为,我们需要回答这个问题通常是如何解决的问题。
好吧,如果您要托管资源,那么您将负责设置响应 header 。以及为 做了什么调试 测试 目的是指定 本地主机 允许访问的端口。
添加 CORS header
例如。如果要运行本地调试和测试,则需要指定要运行的端口。在 Flutter 中,这是通过 --web-port 完成的争论。您可以在 localhost:4200 上运行您的测试使用 --web-port 4200 .
现在,您需要将此本地主机端口添加到响应 header 中允许的来源。可以在 this Google Cloud article 中找到如何执行此操作的示例。 .
在 Chrome 中禁用网络安全
我做什么 不推荐 这样做(因为它不会类似于您的集成测试应该涵盖的真实场景)是 的一种方式。禁用 网络安全。如果您这样做,您可以忽略所有网络安全策略并运行您想要的任何请求。
由于 Flutter Web 集成测试在 Chrome 上运行,you can use --disable-web-security 在 Chrome 设备上禁用网络安全。

关于Flutter Web 集成测试 CORS XMLHttpRequest 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67713165/

相关文章:

android - 更改包名称后 Flutter App 无法正常工作

flutter - Flutter:在SharedPreferences中保存和获取多个值

iPhone 间歇性网络测试

ruby-on-rails - 如何使用 rspec 在 Controller 中测试自定义路由

android - flutter 中有唤醒锁吗?

调用 setState() 时 Flutter FutureBuilder 不更新

php - 如何编码法语/西类牙语字符以使用 clickatell 的 http api?

java - GWT 自动适配复合 Material

c++ - 从 Poco HTTPClientSession 异步读取

php - Web测试用例: Use crawler to test a string