Flutter中Dio无法设置并使用代理发起网络请求问题排查
Flutter 代理请求失效问题解决指南
核心问题分析
你遇到的代理不生效问题,主要源于代码逻辑错误、环境变量配置缺失,以及代理设置的细节疏漏:
- 首次实现中连续调用
dio.useProxy(),第二次调用直接覆盖了从代理池获取的有效代理;且dio.post()未加await导致请求未正确执行。 - 适配器方式设置代理时,存在变量作用域、代理格式校验、认证凭据初始化等问题。
String.fromEnvironment('PROXY_URL')返回空,是因为未在运行/打包阶段传入该环境变量。
修复方案
一、Dio 基础代理设置(最简有效版)
修正代理覆盖问题,确保异步请求正确等待:
class DioProxiedPostRequest extends AbstractWebRequest { DioProxiedPostRequest(super.url, super.headers, super.body); @override Future<WebResponse> send() async { Proxy proxy = await ProxyGetter().getRandomProxy(); String proxyUrl = "${proxy.getHost()}:${proxy.getPort()}"; // 优先使用环境变量代理(如果配置) if (const bool.hasEnvironment('PROXY_URL')) { proxyUrl = const String.fromEnvironment('PROXY_URL'); } Dio dio = Dio(); dio.useProxy(proxyUrl); // 必须添加await等待请求完成 Response response = await dio.post( url, data: json.encode(body), options: Options(headers: headers), ); return DioWebResponse(url, response); } }
二、DefaultHttpClientAdapter 进阶配置(支持代理认证)
如果需要更精细的代理控制(如证书忽略、代理认证),使用适配器方式:
@override Future<WebResponse> send() async { Proxy proxy = await ProxyGetter().getRandomProxy(); String proxyAddress = "${proxy.getHost()}:${proxy.getPort()}"; // 环境变量代理优先级覆盖 if (const bool.hasEnvironment('PROXY_URL')) { proxyAddress = const String.fromEnvironment('PROXY_URL'); } Dio dio = Dio(); (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { // 按需开启:忽略自签名证书(仅Android端建议,iOS需额外配置) client.badCertificateCallback = (cert, host, port) => Platform.isAndroid; // 强制所有请求走代理 client.findProxy = (url) => 'PROXY $proxyAddress'; // 代理需要认证时添加凭据(无认证可删除此段) final proxyParts = proxyAddress.split(':'); if (proxyParts.length == 2) { client.addProxyCredentials( proxyParts[0], int.parse(proxyParts[1]), 'main', HttpClientBasicCredentials('代理用户名', '代理密码'), ); } return client; }; try { Response response = await dio.post( url, data: json.encode(body), options: Options(headers: headers), ); return DioWebResponse(url, response); } catch (e) { // 代理连接失败时可添加重试逻辑 rethrow; } }
三、环境变量 PROXY_URL 配置方法
要让String.fromEnvironment('PROXY_URL')生效,需在运行/打包时传入参数:
- 本地运行命令:
flutter run --dart-define=PROXY_URL=xxx.xxx.xxx.xxx:xxxx - Android 打包命令:
flutter build apk --dart-define=PROXY_URL=xxx.xxx.xxx.xxx:xxxx
四、http 包代理设置方法
如果需要使用原生http包,配置方式如下:
import 'dart:io'; import 'package:http/http.dart' as http; import 'dart:convert'; Future<http.Response> sendProxiedRequest(String url, Map<String, String> headers, Map<String, dynamic> body) async { Proxy proxy = await ProxyGetter().getRandomProxy(); final proxyHost = proxy.getHost(); final proxyPort = int.parse(proxy.getPort()); final httpClient = HttpClient(); httpClient.findProxy = (uri) => 'PROXY $proxyHost:$proxyPort'; httpClient.badCertificateCallback = (cert, host, port) => Platform.isAndroid; final client = IOClient(httpClient); try { return await client.post( Uri.parse(url), headers: headers, body: json.encode(body), ); } finally { client.close(); } }
额外注意事项
- 免费代理池(如us-proxy.org)的代理可用性极低,建议添加代理预校验逻辑(比如请求
httpbin.org/get验证返回的origin是否为代理IP)。 - 即使使用代理,也需控制请求频率,避免触发目标网站的反爬机制。
- iOS端忽略证书需在
Info.plist中添加ATS配置,否则代理请求会被拦截。
内容的提问来源于stack exchange,提问作者JGoss
相关产品推荐
相关产品推荐

