【Flutter_Web】Flutter编译Web第三篇(网络请求篇):dio如何改造方法,变成web之后数据如何处理

前言

Flutter端在处理网络请求的时候,最常用的库当然是Dio了,那么在改造成web端的时候,最先处理的必然是网络请求,否则没有数据去处理驱动实图渲染。

官方链接

  • pub
bash 复制代码
https://pub.dev/packages/dio
  • github
bash 复制代码
https://github.com/cfug/dio/blob/main/dio/README-ZH.md

适配器问题

这里根据官网的指引去看web相关的配置,发现只需要更改适配器HttpClientAdapter即可,放出官方的截图:

然后我想说,这就是一个坑!!!,配置上去运行起来是不可用的。但是我们后面再说这个问题。

我们为了兼容多平台运行,必须使用条件编译的方式进行引入:

这里我建立了三个文件:

ai_network_mobile_adapter.dart作为移动端的适配器移动端是支持代理的

bash 复制代码
import 'package:dio/dio.dart';
import 'package:dio/io.dart';

HttpClientAdapter getAdapter() {
  return IOHttpClientAdapter(
      // createHttpClient: () {
      //   final client = HttpClient();
      //   client.findProxy = (uri) {
      //     return 'PROXY 192.168.11.26:8888';
      //   };
      //   client.badCertificateCallback =
      //       (X509Certificate cert, String host, int port) => true; //忽略证书
      //   return client;
      // },
      );
}

ai_network_web_adapter.dart:web端适配器

bash 复制代码
import 'package:dio/browser.dart';
import 'package:dio/dio.dart';

HttpClientAdapter getAdapter() {
  final adapter = HttpClientAdapter() as BrowserHttpClientAdapter;
  adapter.withCredentials = true;
  return adapter;
}

再通过条件编译文件去引入:

bash 复制代码
export 'ai_network_web_adapter.dart'
    if (dart.library.html) 'ai_network_web_adapter.dart'
    if (dart.library.io) 'ai_network_mobile_adapter.dart';

这样我们只需要使用getAdapter方法,条件编译会自动帮我们选中不同端的适配器。

这里不能用官网的方式去写,一定要这么写,这样才有效:

bash 复制代码
HttpClientAdapter getAdapter() {
  final adapter = HttpClientAdapter() as BrowserHttpClientAdapter;
  adapter.withCredentials = true;
  return adapter;
}

请求加解密

在移动端为了安全,必然会有请求上面的加解密,这里面涉及一些原生加解密和加解密相关的库文件,但在web端很多库不被支持,这里方式有很多,跟后端商量一下就可以,加特殊参数或者使用c的方式,这里不做过多赘述,不过也是时间问题和增加爆破成本。

跨域问题

跨域问题在浏览器环境是必然会出现的,特别是在本地调试的时候,这里我看了网上有很多种方案,大多都是做一层代理,可以使用浏览器插件 ,像我上一篇文章提到的插件,或者使用shelf_proxy

bash 复制代码
import 'dart:io';

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

/// 命令 : dart ./lib/proxy_config.dart
void configServer(HttpServer server) {
  // 这里设置请求策略,允许所有
  server.defaultResponseHeaders.add('Access-Control-Allow-Origin', '*');
  server.defaultResponseHeaders.add('Access-Control-Allow-Credentials', true);
  server.defaultResponseHeaders.add('Access-Control-Allow-Methods', '*');
  server.defaultResponseHeaders.add('Access-Control-Allow-Headers', '*');
  server.defaultResponseHeaders.add('access-control-expose-headers', '*');
  print('Serving at http://${server.address.host}:${server.port}');
}

Future<void> main() async {
  var reqHandle = proxyHandler("http://example.com/"); //要代理的域名

  /// 绑定本地端口,4500,转发到真正的服务器中
  var reqServer = await shelf_io.serve(reqHandle, 'localhost', 4500);
  configServer(reqServer);
}

开启一个代理服务器也可以。

不过还有一种简单的方式:

直接关闭浏览器的安全模式:

bash 复制代码
 "args": [
                "--target",
                "lib/main.dart",
                "--web-browser-flag",
                "--disable-web-security",
                "--web-renderer",
                "html"
            ],

当然最终上线还是要跟后端沟通好请求数据的要求。

预检请求或CORS问题

浏览器对于复杂请求会发出一个预检请求,也就是方法为OPTIONS的,这就是为什么在web端,同一个接口会触发两次的原因。

然后问题就来了,我的请求是Post,并且数据格式也是多表单数据,为什么还会发出OPTIONS请求呢,因为OPTIONS请求是先直接访问你的一级域名,然后不带任何数据去请求访问后端是否允许发送跨域请求的,这个时候正常都不会支持,因为明明可以直接发送数据,不需要多一次预检请求,发了反而失败了导致CORS,然后就不发送正常的请求了。

所以问题的关键在于,dio什么情况下会让你的请求变成复杂的请求?

这里我就去官方github仓库看了,发现不少人也提出了这样的问题,分享这一个问题吧:

bash 复制代码
https://github.com/cfug/dio/issues/2125

标题就是:Flutter web - simple request causing OPTIONS request

为什么简单的请求会发出OPTIONS 请求呢?

这位同学就说了:

如果你在web端,使用了connectTimeout / sendTimeout / onSendProgress这三个函数,在web端没有什么意义,反而会造成CORS,所以我在web端,单独对这三个方法做了null处理,结果确实是不会发送OPTIONS请求了。

我还没仔细去看这三个函数在源码中的实现,有时间会去研究一下,但是确实是解决了问题。

网络状态检测

之前在移动端可能会使用dio去做网络状态检测,能访问的通,就是有网络,这在web端是不可靠的,因为web端有跨域问题,访问其他域名大概率会失败,但失败不意味着你没有网络,因此可以使用web端原生的方法去检测网络。

结论

如果你有更多有趣的想法,欢迎在下方留言,我在查找很多关于flutter转web相关的内容,发现解决方案真的很少,很多都必须从官方仓库去获取,希望能给你带来一些帮助。

相关推荐
极客互动API3 分钟前
企业微信 iPad 协议服务搭建与 AI 回调实战
网络·汇编·人工智能·微信·企业微信·ipad
QH1392923188017 分钟前
Keysight N5183B N5183B 微波模拟信号发生器
网络·单片机·嵌入式硬件·集成测试·信息与通信
LabVIEW开发28 分钟前
基于原始套接字实现LabVIEW网络Ping检测的编程方法
网络·labview·labview知识·labview功能·labview程序
CappuccinoRose40 分钟前
模块化体系
前端·import·export·es modules
东莞和裕包装1 小时前
如何管控广州定制纸箱生产中的啤切精度与印刷色差质量问题
大数据·运维·网络·人工智能
AIDANHANG1 小时前
放开靠时间戳对日志前先核请求ID跨服务传播与采样关联
前端·人工智能
Zguigo2 小时前
lesson19-23计算机网络数据链路层完全指南:从帧封装到滑动窗口协议
网络·计算机网络
半生过往3 小时前
前端学 Java 课程笔记
java·前端·笔记
广州华水科技3 小时前
2026年单北斗GNSS变形监测系统推荐,破解水库安全监测难题
前端
独爱香菜4 小时前
Next.js 15 + Cloudflare Workers 实战:零中间件多语言 SEO 站点架构
前端