使用HTTP软件包由于CORS而失败的flutter Web请求

发布于 2025-02-10 12:35:56 字数 4594 浏览 1 评论 0原文

背景

我正在使用 github codespaces ,该端口可为本地固定应用程序转发。因此,当我运行时,运行-D Web-Server -web-hostname 127.0.0。 -web-port localhost URL用githubpreview.dev url镜像。

在客户端,我具有测试与数据库的连接的功能:

static Future<bool> testConnection() async {
    http.Response response = await _httpClient.get(
      Uri.parse(baseUrl + 'test'), // requestObject.slug.string
      headers: {
        HttpHeaders.authorizationHeader: 'Bearer 69',
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Headers":
            "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
        "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS"
      },
    );

_httpclienthttpclient()的包装器。 在服务器端,我具有以下功能:

export function use_test(request) {
    console.log(`test request:${request.headers.origin}`);
    let options = {
        "headers":{
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials": "true",
            "Access-Control-Allow-Headers":
                "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
            "Access-Control-Allow-Methods":
                "GET, POST, PUT, PATCH, DELETE, OPTIONS"
          },
        "body": {
            "payload": {
                "msg": request['headers']
            }
        }
    };
    return ok(options);
}

每当

运行testConnection时,该请求已成功发送,因为服务器登录了传入请求,但是服务器发送的响应未通过客户端,XMLHTTPREQUESTERROR失败。现在,我在编写Flutter Web应用程序时多次遇到此错误,但是这个错误使我陷入困境。 Postman 可以接收数据,所以我很确定

其他信息

扑动医生输出:

[✓] Flutter (Channel master, 3.1.0-0.0.pre.1354, on Debian GNU/Linux 11 (bullseye) 5.4.0-1074-azure, locale
    en_US.UTF-8)
    • Flutter version 3.1.0-0.0.pre.1354 on channel master at /workspaces/Lighthouse-Web/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision a30012b275 (3 days ago), 2022-06-22 17:04:07 -0700
    • Engine revision fc08bf45b0
    • Dart version 2.18.0 (build 2.18.0-216.0.dev)
    • DevTools version 2.14.0

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[✗] Linux toolchain - develop for Linux desktop
    ✗ clang++ is required for Linux development.
      It is likely available from your distribution (e.g.: apt install clang), or can be downloaded from
      https://releases.llvm.org/
    ✗ CMake is required for Linux development.
      It is likely available from your distribution (e.g.: apt install cmake), or can be downloaded from
      https://cmake.org/download/
    ✗ ninja is required for Linux development.
      It is likely available from your distribution (e.g.: apt install ninja-build), or can be downloaded from
      https://github.com/ninja-build/ninja/releases
    ✗ pkg-config is required for Linux development.
      It is likely available from your distribution (e.g.: apt install pkg-config), or can be downloaded from
      https://www.freedesktop.org/wiki/Software/pkg-config/

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).

[✓] Connected device (1 available)
    • Linux (desktop) • linux • linux-x64 • Debian GNU/Linux 11 (bullseye) 5.4.0-1074-azure

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 4 categories.

如何解决此问题?

Background

I am using GitHub Codespaces, which does port forwarding for locally-hosted applications. So when I run flutter run -d web-server --web-hostname 127.0.0. --web-port the localhost URL is mirrored with a githubpreview.dev URL.

On the client side, I have a function to test the connection with the database:

static Future<bool> testConnection() async {
    http.Response response = await _httpClient.get(
      Uri.parse(baseUrl + 'test'), // requestObject.slug.string
      headers: {
        HttpHeaders.authorizationHeader: 'Bearer 69',
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Headers":
            "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
        "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS"
      },
    );

_httpClient is a wrapper over HttpClient().
On the server side, I have the function as follows:

export function use_test(request) {
    console.log(`test request:${request.headers.origin}`);
    let options = {
        "headers":{
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials": "true",
            "Access-Control-Allow-Headers":
                "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
            "Access-Control-Allow-Methods":
                "GET, POST, PUT, PATCH, DELETE, OPTIONS"
          },
        "body": {
            "payload": {
                "msg": request['headers']
            }
        }
    };
    return ok(options);
}

Issue

Whenever testConnection is run, the request is sent successfully, since the server logs the incoming request, but the response sent by the server is not received by the client, failing with an XMLHttpRequestError. Now, I have come across this error many times when writing Flutter Web applications, but this one stumps me. Postman can receive the data all right, so I'm pretty sure CORS is to blame for this issue.

Additional Information

Flutter doctor output:

[✓] Flutter (Channel master, 3.1.0-0.0.pre.1354, on Debian GNU/Linux 11 (bullseye) 5.4.0-1074-azure, locale
    en_US.UTF-8)
    • Flutter version 3.1.0-0.0.pre.1354 on channel master at /workspaces/Lighthouse-Web/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision a30012b275 (3 days ago), 2022-06-22 17:04:07 -0700
    • Engine revision fc08bf45b0
    • Dart version 2.18.0 (build 2.18.0-216.0.dev)
    • DevTools version 2.14.0

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[✗] Linux toolchain - develop for Linux desktop
    ✗ clang++ is required for Linux development.
      It is likely available from your distribution (e.g.: apt install clang), or can be downloaded from
      https://releases.llvm.org/
    ✗ CMake is required for Linux development.
      It is likely available from your distribution (e.g.: apt install cmake), or can be downloaded from
      https://cmake.org/download/
    ✗ ninja is required for Linux development.
      It is likely available from your distribution (e.g.: apt install ninja-build), or can be downloaded from
      https://github.com/ninja-build/ninja/releases
    ✗ pkg-config is required for Linux development.
      It is likely available from your distribution (e.g.: apt install pkg-config), or can be downloaded from
      https://www.freedesktop.org/wiki/Software/pkg-config/

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).

[✓] Connected device (1 available)
    • Linux (desktop) • linux • linux-x64 • Debian GNU/Linux 11 (bullseye) 5.4.0-1074-azure

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 4 categories.

How can I fix this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

老旧海报 2025-02-17 12:35:56

对于那些想知道如何解决此问题的人,我从dart使用httprequest.requestcrossorigin dart:html而不是httpclient代码>软件包。

示例代码

每当跨原始请求被阻止时,通常是因为服务器的响应没有正确的CORS权限,并且在到达客户端之前会被浏览器阻止。为了解决这个问题,我们需要在服务器代码中添加以下标题(在我的情况下server.js):

function options(origin) {
    return {
        "headers": {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": origin,
            "Access-Control-Allow-Credentials": true,
        },
        "body": {
            ...
        }
    }
}

为每个请求生成到服务器的每个请求,一个模板响应,该响应启用请求的源在CORS许可中。然后可以在端点的其余代码中修改此响应,以将有效载荷添加到body等。

接下来,服务器中的端点看起来像这样:

export async function use_postTest(request) {
    // The body of the POST request, stored as a JSON object
    let reqBody = JSON.parse(await request.body.text());
    // Create the template response with the incoming origin
    let res = options(request.headers.origin);
    // Modifying the response data
    res.status = res.body.status.code = 200;
    res.body.status.msg = "All ok!";
    // Passing the incoming request body back to the client, to show that the POST request can be processed
    res.body.payload.push(reqBody);
    return response(res);
}

顺便说一句,我们现在对客户端进行编码。请注意,此解决方案仅适用于Flutter Web应用程序,因为它使用dart:html,仅适用于Web平台的一组服务。

我们的.dart文件具有以下代码,可以使用JSON主体发送发布请求:

import 'dart:convert';
import 'dart:html';

Future<void> postCrossOrigin() async {
  final HttpRequest request = await HttpRequest.request(
    "https://...",
    method: 'POST',
    // the Map has to be encoded using jsonEncode
    sendData: jsonEncode({
      'a': 1,
      'b': [2, 3, 4],
      'c': true,
    }),
  );
  // Alternatively, use jsonDecode(request.responseText) to convert the response to a native Map object
  print(request.responseText);
}

Flutter Run -D Chrome以在控制台中获得以下结果:

{"status":{"code":200,"msg":"All ok!"},"payload":[{"a":1,"b":[2,3,4],"c":true}]}

希望这会有所帮助!

For those wondering how to solve this problem, I used HttpRequest.requestCrossOrigin from dart:html instead of HttpClient from the http package.

Sample Code

Whenever a cross-origin request is blocked, it is typically because the response from the server does not have the right CORS permissions, and is blocked by the browser before reaching the client. To remedy this, we need to add in the following headers in our server code (server.js in my case):

function options(origin) {
    return {
        "headers": {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": origin,
            "Access-Control-Allow-Credentials": true,
        },
        "body": {
            ...
        }
    }
}

This generates, for each request to the server, a template response that enables the request's origin in the CORS permissions. This response can then be modified throughout the rest of the endpoint's code to add payload to the body and such.

Next, the endpoint in the server looks like this:

export async function use_postTest(request) {
    // The body of the POST request, stored as a JSON object
    let reqBody = JSON.parse(await request.body.text());
    // Create the template response with the incoming origin
    let res = options(request.headers.origin);
    // Modifying the response data
    res.status = res.body.status.code = 200;
    res.body.status.msg = "All ok!";
    // Passing the incoming request body back to the client, to show that the POST request can be processed
    res.body.payload.push(reqBody);
    return response(res);
}

That aside, we now code the client. Take note that this solution is only for Flutter Web apps, since it uses dart:html, a set of services only available for the web platform.

Our .dart file has the following code to send POST requests with JSON bodies:

import 'dart:convert';
import 'dart:html';

Future<void> postCrossOrigin() async {
  final HttpRequest request = await HttpRequest.request(
    "https://...",
    method: 'POST',
    // the Map has to be encoded using jsonEncode
    sendData: jsonEncode({
      'a': 1,
      'b': [2, 3, 4],
      'c': true,
    }),
  );
  // Alternatively, use jsonDecode(request.responseText) to convert the response to a native Map object
  print(request.responseText);
}

flutter run -d chrome to obtain the following result in the console:

{"status":{"code":200,"msg":"All ok!"},"payload":[{"a":1,"b":[2,3,4],"c":true}]}

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文