Flutter Web 跨域问题解决方案

16,180 阅读3分钟

最近对Flutter Web产生了兴趣,之前一直在用Flutter写客户端,感觉写的很爽,既然Flutter对Web也进行了支持,我为啥不写一个web的来玩一下呢? 然后着手写,静态页面写起来基本没啥问题,可是想加接口的时候,却遇到了浏览器跨域问题,很荣幸解决掉了,废话不多说,下面来分享下如何解决的吧:


前置条件:

待请求接口:https://developer.mozilla.org/api/v1/whoami 这里我们拿这个接口来试验

正常我们使用dio访问:

Response response = await dio.get("https://developer.mozilla.org/api/v1/whoami");

一定会遇到这个问题:

很明显,浏览器给限制跨域了。怎么解决呢?


解决方案其实蛮多的,对纯前端来说方案很多,Flutter呢,我比较推荐的这几个方法是:

  1. chrome 安装这个插件 插件地址

安装后,简单配置下下面图中的一些值即可,主要就是

Request headers:要代理的地址,
Response headers:*,
Access-Control-Allow-Headers:true

然后在Web页面打开对应的开关即可。

  1. 配置Nginx,配置太多这里就不说了,网上很多。
  2. 接下来我们重点讲一下flutter特有的方式,参考思路来源前端的解决方案,先来看下前端的方案,对应文章地址:juejin.im/post/684490…

看到了这里,我正好周末看到dart可以写服务器,那是不是可以参考下? 于是我找到了这个:

shelf_proxy 简单封装了一下: shelf

很早前我还看到过这个,不知干啥的,现在用到了,才知道原来如此,虽然star不多,但却是Dart官方的,用于本地调试接口使用,还是很靠谱的。

对应到我项目里怎么用的呢?我们来看下 关键代码

import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_proxy/shelf_proxy.dart';

//前端页面访问本地域名
const String LocalHost = 'localhost';

//前端页面访问本地端口号
const int LocalPort = 4040;

//目标域名,这里我们将要请求火狐的这个地址
const String TargetUrl = 'https://developer.mozilla.org';

Future main() async {
  var server = await shelf_io.serve(
    proxyHandler(TargetUrl),
    LocalHost,
    LocalPort,
  );
  // 添加上跨域的这几个header
  server.defaultResponseHeaders.add('Access-Control-Allow-Origin', '*');
  server.defaultResponseHeaders.add('Access-Control-Allow-Credentials', true);

  print('Serving at http://${server.address.host}:${server.port}');
}

然后我把上面的这段代码,保存到前端的一个文件夹里面,放在lib/server/cors.dart,然后打开命令行,运行:dart ./lib/server/cors.dart,代理服务器启动了!

接下来,我们前端的flutter代码,也就是上面的请求,改成

Response response = await dio.get("http://localhost:4040/api/v1/whoami");

接下来点请求,果然正常拿到结果:

到这为止,跨域的问题完美解决,全部用dart来解决了(这是我最想要的)!😸

当然了,这只是个demo级别的代码,还有很多细的东西可以重写定制。 如果大家有什么更好的建议,欢迎告诉我哦~

ps:为什么要把这个服务文件放在前端,目的是依赖库可以直接用,再就是运行代理服务也方便,后面可以跟运行代码一起启动,比如写个批处理是吧。。。

另外,现在应该运行不行,最近调试了下,需要改动一下shelf_proxy源码,增加对options的支持,可以参考这个change:github.com/dart-lang/s…