You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web使用http包发起请求因CORS报错的解决方案

问题背景

当前使用GitHub Codespaces进行开发,平台自带本地托管应用的端口转发能力。执行flutter run -d web-server --web-hostname 127.0.0. --web-port命令启动服务时,本地localhost地址会被映射为githubpreview.dev域名的公网可访问地址。

客户端侧编写了数据库连通性测试函数,代码如下:

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是对HttpClient()的封装。

服务端对应处理函数代码如下:

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发起相同请求可以正常拿到返回数据,初步判断是CORS跨域机制导致的故障。

补充信息

Flutter doctor执行输出如下:

[✓] 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
    • 上游仓库为Flutter官方代码仓库
    • 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.
      安装Android Studio后首次启动会自动引导安装Android SDK组件。
      若已将Android SDK安装到自定义路径,执行`flutter config --android-sdk`更新对应路径即可。

[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)
    ! 无法找到Chrome程序,可设置CHROME_EXECUTABLE环境变量指定Chrome可执行文件路径。

[✗] Linux toolchain - develop for Linux desktop
    ✗ 进行Linux桌面端开发需要安装clang++,可通过系统包管理器安装
    ✗ 进行Linux桌面端开发需要安装CMake,可通过系统包管理器或官方渠道下载
    ✗ 进行Linux桌面端开发需要安装ninja,可通过系统包管理器或官方渠道下载
    ✗ 进行Linux桌面端开发需要安装pkg-config,可通过系统包管理器安装

[!] Android Studio (not installed)
    • 未检测到Android Studio安装,可下载安装后完成对应配置。

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

[✓] HTTP Host Availability
    • 所有需要访问的HTTP主机均可达

! Doctor found issues in 4 categories.

排查修复方案

按优先级从高到低逐个修改即可解决问题:

  • 立刻删掉客户端请求头里所有Access-Control-*开头的字段。这些字段是服务端返回给浏览器的响应头,放在请求里没有任何作用,反而会因为新增非标准自定义头,强制浏览器在发送正式GET请求前先发起OPTIONS预检请求,平白增加跨域校验环节。
  • 修复服务端CORS配置的硬性冲突:CORS规范明确禁止同时设置Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true,二者完全互斥。不需要传递Cookie、TLS客户端凭证这类认证信息的话,直接删掉Access-Control-Allow-Credentials: true配置即可;如果需要传递凭证,就把Access-Control-Allow-Origin的值设置为请求实际的Origin值(也就是你服务端日志打印的request.headers.origin内容),绝对不能用通配符。
  • 给服务端补充OPTIONS预检请求的处理逻辑。当前你的服务端只处理了GET方法的/test路由,浏览器发出的OPTIONS预检请求没有对应处理逻辑,要么返回4xx错误,要么返回的响应没带正确CORS头,浏览器会直接判定跨域失败,拦截后续所有响应。处理逻辑非常简单:所有OPTIONS方法的请求直接返回204状态码,带上和GET响应一致的CORS头即可,不需要返回任何业务内容。
  • 修正Flutter启动命令:你当前写的--web-hostname 127.0.0.参数有误,漏了最后一位地址段,且在Codespaces环境下要让端口转发正常生效,必须绑定0.0.0.0地址,参考正确启动命令:flutter run -d web-server --web-hostname 0.0.0.0 --web-port 自定义端口号。
  • 检查Codespaces端口转发配置:在Codespaces的端口管理面板中,找到后端服务对应的转发端口,将可见性设置为公开,同时确认代码里baseUrl配置的地址和端口转发生成的访问地址完全匹配,不要出现前端跑在githubpreview.dev域名、baseUrl却写localhost的情况。

注意:Postman能正常请求不代表CORS配置正确。Postman作为接口调试工具,本身不受浏览器CORS安全规则限制,不会自动发送预检请求,也不会拦截跨域响应,完全不能作为CORS配置的校验依据。


内容的提问来源于stack exchange,提问作者Obsidian418

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:21:26