Flutter 中自定义DNS解析的实现
为了提升Flutter中网络请求的速度,集成了阿里云的DNS解析服务,在官方示例中未提供基于Dio的实现, 因此经过调研后,尝试基于Dio进行自定义扩展实现,最开始做的时候,首先想到的是使用自定义Dio的拦截器进行实现,经过一系列的调研后,发现Dio中拦截器的执行顺序是在DNS解析之后,所以即使在拦截器中实现了DNS解析,也毫无意义,因此采用了自定义Proxy代理的方式进行实现。
第一步创建Proxy
class DomainHttpClientAdapter extends HttpClientAdapter {@overridevoid close({bool force = false}) {}//需要解析的域名var spareHostArray = ["taobo",];@overrideFuture<ResponseBody> fetch(RequestOptions options, Stream<Uint8List>? requestStream, Future<dynamic>? cancelFuture) async {// 自定义 DNS 解析LogUtils.d("DomainHttpClientAdapter------------>fetch-->${options.uri.host}");Uri newUri = options.uri;if (spareHostArray.contains(options.uri.host)) {String host = options.uri.host;String ipAddress = await _resolveHostToIp(host);int port = options.uri.port;String scheme = options.uri.scheme;String newPath = '$scheme://$ipAddress:$port${options.uri.path}${options.uri.query}';LogUtils.d("DomainHttpClientAdapter------------>newPath->$newPath-->");options.baseUrl = newPath;options.path = "";}final HttpClient httpClient = HttpClient();LogUtils.d("DomainHttpClientAdapter------------>openUrl-newUri->$newUri--baseUrl->${options.baseUrl}");final HttpClientRequest httpRequest = await httpClient.openUrl(options.method, newUri);// 设置请求头options.headers.forEach((key, value) {httpRequest.headers.set(key, value);});// 写入请求体if (requestStream != null) {await requestStream.forEach(httpRequest.add);}final HttpClientResponse httpResponse = await httpRequest.close();// 读取响应数据final List<int> responseBody = await httpResponse.fold([], (List<int> a, List<int> b) => a..addAll(b));return ResponseBody.fromBytes(responseBody,httpResponse.statusCode,headers: convertHeaders(httpResponse.headers),statusMessage: httpResponse.reasonPhrase,);}// 将 HttpHeaders 转换为 Dio 需要的 headers 格式Map<String, List<String>> convertHeaders(HttpHeaders headers) {Map<String, List<String>> convertedHeaders = {};headers.forEach((name, values) {convertedHeaders[name] = values;});return convertedHeaders;}///使用通道,发送消息到原生进行DNS解析Future<String> _resolveHostToIp(String host) async {try{var ip = await ChannelManager.getInstance().sendMessage("getIpByHost",host);LogUtils.d("DomainHttpClientAdapter------------>_resolveHostToIp-->$ip");return ip;}catch(e){return host;}}
}
第二步,给Dio增加自定义代理
dio.httpClientAdapter = DomainHttpClientAdapter();
通过如上两步即可实现Flutter中自定义DNS解析,本案例只作为参考,提供一种自定义解析DNS的实现方案,具体实现,可根据自己项目进行定制实现。