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

news/2024/12/28 16:38:53/

前言

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

官方链接

  • pub
https://pub.dev/packages/dio
  • github
https://github.com/cfug/dio/blob/main/dio/README-ZH.md

适配器问题

这里根据官网的指引去看web相关的配置,发现只需要更改适配器HttpClientAdapter即可,放出官方的截图:
在这里插入图片描述
然后我想说,这就是一个坑!!!,配置上去运行起来是不可用的。但是我们后面再说这个问题。

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

这里我建立了三个文件:
ai_network_mobile_adapter.dart作为移动端的适配器移动端是支持代理的

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端适配器

import 'package:dio/browser.dart';
import 'package:dio/dio.dart';HttpClientAdapter getAdapter() {final adapter = HttpClientAdapter() as BrowserHttpClientAdapter;adapter.withCredentials = true;return adapter;
}

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

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方法,条件编译会自动帮我们选中不同端的适配器。

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

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

请求加解密

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

跨域问题

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

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);
}

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

不过还有一种简单的方式:
直接关闭浏览器的安全模式:

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

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

预检请求或CORS问题

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

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

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

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

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相关的内容,发现解决方案真的很少,很多都必须从官方仓库去获取,希望能给你带来一些帮助。


http://www.ppmy.cn/news/1558835.html

相关文章

基于Oauth2的SSO单点登录---后端

【springbootvue项目&#xff08;十三&#xff09;】 Springboot整合Spring SecurityJWT 【springbootvue项目&#xff08;十四&#xff09;】基于Oauth2的SSO单点登录&#xff08;一&#xff09;整体流程介绍 【springbootvue项目&#xff08;十五&#xff09;】基于Oauth2的…

HTML5文档元数据详解

HTML5文档元数据详解 在HTML5中&#xff0c;元数据&#xff08;Meta Data&#xff09;是文档头部的重要组成部分&#xff0c;提供了关于网页本身的信息。以下是一些常见的元数据标签及其详细说明。 1. <meta> 标签 <meta>标签用于定义文档的元数据&#xff0c;通…

matlab遇到的各种问题及解决方案

&#x1f642;本文整理了自己学习matlab过程中遇到的一些问题&#xff0c;及在网上找到的解决方法&#xff0c;并记录下来&#xff0c;方便后续学习&#xff0c;文章出处已附上链接&#x1f642;~ “变量似乎要更改脚本中每个循环迭代的大小。请考虑对速度进行预分配。” MAT…

cesium通过经纬度获取3dtiles 得feature信息

找到这里3dtiles的两种访问方式&#xff1a; 1.1 3DTileContent#getFeature 这里涉及3DTile 数据结构&#xff0c;暂不了解3DTile 数据结构&#xff0c;因此暂不使用。 1.2 scene.pick 本次使用 scene表示虚拟场景中所有 3D 图形对象和状态的容器&#xff1b;scene中…

C++-------递归知识点串讲

C递归简介 递归的定义&#xff1a;递归是指在函数的定义中使用函数自身的方法。一个递归函数通常包含两部分&#xff1a;基线条件&#xff08;base case&#xff09;和递归条件&#xff08;recursive case&#xff09;。基线条件用于终止递归&#xff0c;防止无限循环&#xf…

虚拟机桥接模式网络连接不上解决方法

可能是桥接模式自动配置网络地址的时候没配好&#xff0c;自己手动配置一下。先看看windows里的wifi的ip 把虚拟机的网络设置打开ipv4把地址、子网掩码、网关输进去&#xff0c;然后再连接

leetcode 3083. 字符串及其反转中是否存在同一子字符串 简单

给你一个字符串 s &#xff0c;请你判断字符串 s 是否存在一个长度为 2 的子字符串&#xff0c;在其反转后的字符串中也出现。 如果存在这样的子字符串&#xff0c;返回 true&#xff1b;如果不存在&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;s "…

matlab客户端最新功能:使用vs code的github copilot编写mlx实时脚本文件

Github的copilot可以大大提高编程速率&#xff0c;但是只能在VS code里应用。 对于很多使用matlab的同学来说很不方便。因为vs code打不开.mlx文件. 不过现在有了解决办法。 官方提供了vscode的matlab插件。但是这个插件只能对编写的代码进行高亮和提示&#xff0c;还是没法打…