Flutter DNS查询插件doh_api_client的使用
Flutter DNS查询插件doh_api_client的使用
特性
- 使用DNS over HTTPS (DoH)协议进行HTTP请求(GET, POST, PUT, PATCH, DELETE)
- 支持12种不同的DoH提供商
- 易于与Flutter项目集成
- 原生实现以提高性能(Android上使用OKHTTP,iOS上使用URLSession)
安装
在pubspec.yaml
文件中添加以下依赖:
dependencies:
doh_api_client: ^1.0.0
然后运行:
flutter pub get
使用方法
首先,在你的Dart文件中导入插件:
import 'package:doh_api_client/doh_api_client.dart';
发送API请求
以下是如何使用DoH API客户端发送POST请求的示例:
final _dohApiClientPlugin = DohApiClient();
try {
String apiPostRequest = await _dohApiClientPlugin.post(
url: "https://jsonplaceholder.typicode.com/posts",
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
'Content-type': 'application/json; charset=UTF-8'
},
body: jsonEncode({
"title": 'foo',
"body": 'bar',
"userId": 1,
}),
dohProvider: DohProvider.CloudFlare
);
print(apiPostRequest);
} catch (e) {
print("Error occurred: $e");
}
可用的DoH提供商
该插件支持以下DoH提供商:
- CloudFlare
- AdGuard
- Quad9
- AliDNS
- DNSPod
- threeSixty
- Quad101
- Mullvad
- ControlD
- Najalla
- SheCan
你可以通过DohProvider
枚举指定DoH提供商。
API参考
DohApiClient
这是用于发送API请求的主要类。
方法
Future<String?> get({required String url, Map<String, String>? headers, DohProvider dohProvider})
Future<String?> post({required String url, Map<String, String>? headers, required String body, DohProvider dohProvider})
Future<String?> put({required String url, Map<String, String>? headers, required String body, DohProvider dohProvider})
Future<String?> patch({required String url, Map<String, String>? headers, required String body, DohProvider dohProvider})
Future<String?> delete({required String url, Map<String, String>? headers, DohProvider dohProvider})
示例代码
import 'dart:convert';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:doh_api_client/doh_api_client.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _dohApiClientPlugin = DohApiClient();
String _apiGetRequest = "";
String _apiPostRequest = "";
String _apiPutRequest = "";
String _apiPatchRequest = "";
String _apiDeleteRequest = "";
[@override](/user/override)
void initState() {
super.initState();
initPlatformState();
}
// 平台消息是异步的,所以我们初始化时使用异步方法。
Future<void> initPlatformState() async {
String apiGetRequest;
String apiPostRequest;
String apiPutRequest;
String apiPatchRequest;
String apiDeleteRequest;
// 平台消息可能失败,所以我们使用try/catch处理PlatformException。
// 我们还处理消息可能返回null的情况。
try {
apiGetRequest = await _dohApiClientPlugin.get(
url: "https://jsonplaceholder.typicode.com/posts/1",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
},
dohProvider: DohProvider.CloudFlare) ??
"Method Channel Called for GET Request but Failure Received";
setState(() {
_apiGetRequest = apiGetRequest;
});
} catch (e) {
apiGetRequest = "Method Channel Failed to call for GET Request";
setState(() {
_apiGetRequest = apiGetRequest;
});
}
try {
apiPostRequest = await _dohApiClientPlugin.post(
url: "https://jsonplaceholder.typicode.com/posts",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
'Content-type': 'application/json; charset=UTF-8'
},
body: jsonEncode({
"title": 'foo',
"body": 'bar',
"userId": 1,
}),
dohProvider: DohProvider.CloudFlare) ??
"Method Channel Called for POST Request but Failure Received";
setState(() {
_apiPostRequest = apiPostRequest;
});
} catch (e) {
apiPostRequest = "Method Channel Failed to call for POST Request";
setState(() {
_apiPostRequest = apiPostRequest;
});
}
try {
apiPutRequest = await _dohApiClientPlugin.put(
url: "https://jsonplaceholder.typicode.com/posts/1",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
'Content-type': 'application/json; charset=UTF-8'
},
body: jsonEncode({
"id": 1,
"title": 'foo',
"body": 'bar',
"userId": 1,
}),
dohProvider: DohProvider.CloudFlare) ??
"Method Channel Called for PUT Request but Failure Received";
setState(() {
_apiPutRequest = apiPutRequest;
});
} catch (e) {
apiPutRequest = "Method Channel Failed to call for PUT Request";
setState(() {
_apiPutRequest = apiPutRequest;
});
}
try {
apiPatchRequest = await _dohApiClientPlugin.patch(
url: "https://jsonplaceholder.typicode.com/posts/1",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
'Content-type': 'application/json; charset=UTF-8'
},
body: jsonEncode({
"title": 'foo',
}),
dohProvider: DohProvider.CloudFlare) ??
"Method Channel Called for PATCH Request but Failure Received";
setState(() {
_apiPatchRequest = apiPatchRequest;
});
} catch (e) {
apiPatchRequest = "Method Channel Failed to call for PATCH Request";
setState(() {
_apiPatchRequest = apiPatchRequest;
});
}
try {
apiDeleteRequest = await _dohApiClientPlugin.delete(
url: "https://jsonplaceholder.typicode.com/posts/1",
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
},
dohProvider: DohProvider.CloudFlare) ??
"Method Channel Called for DELETE Request but Failure Received";
setState(() {
_apiDeleteRequest = apiDeleteRequest;
});
} catch (e) {
apiDeleteRequest = "Method Channel Failed to call for DELETE Request";
setState(() {
_apiDeleteRequest = apiDeleteRequest;
});
}
// 如果小部件从树中被移除,而异步平台消息还在飞行中,我们希望丢弃回复而不是调用setState来更新我们的不存在的外观。
if (!mounted) return;
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('DoH API Client Example'),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("GET Request: "),
_apiGetRequest.isEmpty
? const CircularProgressIndicator()
: Expanded(child: Text(_apiGetRequest)),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("POST Request: "),
_apiPostRequest.isEmpty
? const CircularProgressIndicator()
: Expanded(child: Text(_apiPostRequest)),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("PUT Request: "),
_apiPutRequest.isEmpty
? const CircularProgressIndicator()
: Expanded(child: Text(_apiPutRequest)),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("PATCH Request: "),
_apiPatchRequest.isEmpty
? const CircularProgressIndicator()
: Expanded(child: Text(_apiPatchRequest)),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("DELETE Request: "),
_apiDeleteRequest.isEmpty
? const CircularProgressIndicator()
: Expanded(child: Text(_apiDeleteRequest)),
],
),
),
],
),
),
),
);
}
}
更多关于Flutter DNS查询插件doh_api_client的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter DNS查询插件doh_api_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用doh_api_client
插件进行DNS查询的示例代码。doh_api_client
是一个支持DNS over HTTPS(DoH)的Flutter插件,可以用于在Flutter应用中执行DNS查询。
首先,确保你已经在pubspec.yaml
文件中添加了doh_api_client
依赖:
dependencies:
flutter:
sdk: flutter
doh_api_client: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter应用中使用这个插件来执行DNS查询。以下是一个简单的示例代码:
import 'package:flutter/material.dart';
import 'package:doh_api_client/doh_api_client.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String? result;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('DoH DNS Query Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'Enter domain name'),
onEditingComplete: () async {
String domain = this.textEditingController.text;
result = await performDnsQuery(domain);
setState(() {});
},
// 为了简化示例,这里直接使用了onEditingComplete,实际应用中可能需要一个按钮来触发查询
controller: TextEditingController()..addListener(() {
if (!this.textEditingController.text.contains('.')) {
// 简单验证,确保输入的是域名
this.textEditingController.value =
this.textEditingController.value.copyWith(
text: this.textEditingController.text,
composing: TextRange.empty,
selection: TextSelection.collapsed(offset: this.textEditingController.text.length),
);
}
}),
),
SizedBox(height: 20),
if (result != null) Text('Result: $result'),
],
),
),
),
);
}
Future<String?> performDnsQuery(String domain) async {
try {
// 创建一个DoH客户端实例
final DohApiClient dohClient = DohApiClient(
url: 'https://dns.google/resolve', // 你可以使用其他DoH服务器,比如Cloudflare的 'https://1.1.1.1/dns-query'
);
// 执行DNS查询
final response = await dohClient.query(domain);
// 处理响应结果
if (response.status == 0) {
// 查询成功,这里只提取第一个A记录作为示例
final firstARecord = response.answer
?.firstWhereOrNull((record) => record.type == RecordType.A)
as? ARecord;
if (firstARecord != null) {
return 'IP Address: ${firstARecord.ip}';
} else {
return 'No A record found.';
}
} else {
return 'Error: ${response.statusMessage}';
}
} catch (e) {
return 'Exception: $e';
}
}
}
请注意,这个示例代码中有几个关键点:
- TextFormField 用于输入域名,并在编辑完成时触发DNS查询。
- DohApiClient 用于执行DNS查询,这里使用了Google的DoH服务器(
https://dns.google/resolve
),你可以根据需要更改为其他DoH服务器。 - performDnsQuery 方法执行DNS查询并处理响应结果,这里只提取了第一个A记录作为示例。
请根据你的实际需求调整代码,并确保你的应用有适当的错误处理和用户反馈机制。