Flutter Web使用Dio请求ngrok接口报XMLHttpRequest错误问题咨询
问题核心成因
你遇到的DioError [DioErrorType.response]: XMLHttpRequest error是Flutter Web端非常典型的跨域拦截问题,和Dio库本身、常规请求逻辑没有直接关联。
出现这个报错的根本原因可以从堆栈信息里直接定位:
- 堆栈中出现
js_dev_runtime标识,说明你的应用是在浏览器的Flutter Web调试环境下运行,网络请求底层完全依赖浏览器的XMLHttpRequest能力实现 - 浏览器的同源策略会拦截所有未获得授权的跨域请求,当你请求的ngrok映射本地服务没有在响应中返回允许跨域的CORS规则时,浏览器会在底层直接阻断请求,根本不会把响应内容传回给Dio
- 浏览器的跨域拦截不会把具体的拦截原因透传给上层应用,所以Dio只能捕获到通用的XMLHttpRequest错误,没有更细的报错信息
- 你之前能正常访问的公开API,本身已经配置好了允许跨域的响应规则,所以不会触发浏览器拦截
代码里的常见误区
你当前写的配置逻辑存在两个会导致问题排查走弯路的错误:
- 配置顺序颠倒:你是在
dio.get()请求已经发起之后,才给Dio实例设置请求头,这些配置根本不会作用在已经发出去的请求上 - 对跨域头的理解错误:
Access-Control-Allow-Origin、Access-Control-Allow-Methods这类响应头只能由被请求的服务端在响应报文中返回,客户端请求携带这类头完全不会生效,浏览器会直接忽略,对解决跨域没有任何帮助
分场景解决方法
场景1:当前为Flutter Web调试环境
核心解决方向是给你的本地后端服务配置正确的CORS响应规则:
- 接口响应需要明确返回允许跨域访问的Origin匹配规则
- 允许GET方法发起的跨域请求,支持浏览器的跨域预检流程
- 响应头需要匹配你请求携带的Content-Type类型
- 如果你使用ngrok做内网映射,可以直接在ngrok启动时添加对应参数,自动给所有映射的接口追加跨域响应头,不需要修改本地服务的业务代码
场景2:后续将应用打包到Android/iOS端遇到同类问题
需要额外排查两项配置:
- 高版本Android系统默认拦截明文HTTP请求,需要在应用的配置文件中手动开放对你使用的ngrok域名的明文访问权限
- 确认运行应用的设备和ngrok服务网络连通,没有本地防火墙、运营商网络策略拦截请求
额外的代码bug提醒
你写的按钮绑定逻辑是RaisedButton(onPressed: getMethod),但实际定义的请求方法名是getCountries,如果绑定的方法名和实际实现的方法名不匹配,会导致按钮点击根本触发不了请求逻辑,注意核对两处的方法名保持一致。
内容的提问来源于stack exchange,提问作者anf
相关产品推荐
相关产品推荐

