为了提升Flutter中网络请求的速度,集成了阿里云的DNS解析服务,在官方示例中未提供基于Dio的实现, 因此经过调研后,尝试基于Dio进行自定义扩展实现,最开始做的时候,首先想到的是使用自定义Dio的拦截器进行实现,经过一系列的调研后,发现Dio中拦截器的执行顺序是在DNS解析之后,所以即使在拦截器中实现了DNS解析,也毫无意义,因此采用了自定义Proxy代理的方式进行实现。
第一步创建Proxy
class DomainHttpClientAdapter extends HttpClientAdapter {
@override
void close({bool force = false}) {
}
//需要解析的域名
var spareHostArray = [
"taobo",
];
@override
Future<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的实现方案,具体实现,可根据自己项目进行定制实现。