HarmonyOS 6实战4:网络代理设置与取消的完整解决方案
方案选择:根据具体业务需求选择合适的取消代理方案错误处理:完善的错误处理机制确保代理配置的可靠性网络感知:结合网络状态智能管理代理配置用户体验:提供清晰的代理状态反馈和操作确认
引言
在HarmonyOS应用开发中,网络代理配置是连接外部服务、访问受限资源的关键技术。华为提供了connection.setAppHttpProxyAPI来设置应用级HTTP代理,但在实际开发中,开发者经常遇到一个棘手问题:设置代理后如何正确取消代理配置? 本文将深入探讨这一问题的解决方案,并提供完整的实战代码示例。
问题背景
典型应用场景
-
企业应用:员工在公司内网需要通过代理服务器访问外部资源,回家后需要自动切换回直连模式
-
安全应用:需要临时通过代理服务器进行安全检测,检测完成后恢复原始网络配置
-
测试应用:开发测试阶段需要通过代理抓包分析,正式发布时需要移除代理配置
-
跨境应用:用户在不同地区需要切换不同的代理服务器,包括关闭代理
技术挑战
-
connection.setAppHttpProxyAPI只提供了设置代理的方法,没有直接的"取消代理"接口 -
错误的代理配置会导致应用网络请求全部失败
-
不同网络环境(Wi-Fi、移动数据)下的代理配置管理复杂
-
需要确保代理配置的变更不会影响其他应用
核心API详解
connection.setAppHttpProxy
// 设置应用级HTTP代理
connection.setAppHttpProxy(
host: string, // 代理服务器主机名
port: number, // 代理服务器端口
exclusionList: Array<string> // 排除列表,这些域名不走代理
): void;
参数说明:
-
host:代理服务器地址,如"proxy.example.com" -
port:代理服务器端口,如8080 -
exclusionList:排除的域名列表,这些域名将直接连接而不通过代理
connection.getDefaultHttpProxy
// 获取默认网络代理配置
connection.getDefaultHttpProxy(callback: AsyncCallback<HttpProxy>): void;
connection.getDefaultHttpProxy(): Promise<HttpProxy>;
// HttpProxy接口定义
interface HttpProxy {
host: string; // 代理主机
port: number; // 代理端口
exclusionList: Array<string>; // 排除列表
pacUrl?: string; // PAC文件URL(可选)
}
重要特性:
-
如果设置了全局代理,返回全局代理配置
-
如果进程绑定到特定网络,返回该网络的代理配置
-
其他情况返回默认网络的代理配置
解决方案一:设置空代理配置
实现原理
通过将代理配置设置为"空值"来达到取消代理的效果。具体来说:
-
将
host设为空字符串"" -
将
port设为0 -
将
exclusionList设为空数组[]
代码实现
import { connection } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
/**
* 方案一:通过设置空代理配置取消代理
* 适用于完全取消代理,恢复直连模式
*/
class ProxyManager {
/**
* 取消应用HTTP代理(方案一)
*/
static cancelAppHttpProxy(): void {
try {
// 设置空代理配置
connection.setAppHttpProxy('', 0, []);
console.info('代理已成功取消(设置为空配置)');
// 验证代理是否已取消
this.verifyProxyCancellation();
} catch (error) {
const err = error as BusinessError;
console.error(`取消代理失败: ${err.code}, ${err.message}`);
throw err;
}
}
/**
* 验证代理是否已成功取消
*/
private static verifyProxyCancellation(): void {
connection.getDefaultHttpProxy((err, proxyInfo) => {
if (err) {
console.error(`获取代理信息失败: ${err.code}, ${err.message}`);
return;
}
if (proxyInfo.host === '' && proxyInfo.port === 0) {
console.info('验证成功:代理配置已清空');
} else {
console.warn(`验证警告:代理配置未完全清空,当前配置: ${JSON.stringify(proxyInfo)}`);
}
});
}
/**
* 设置HTTP代理
* @param host 代理服务器地址
* @param port 代理服务器端口
* @param exclusions 排除的域名列表
*/
static setHttpProxy(host: string, port: number, exclusions: string[] = []): void {
try {
// 参数验证
if (!host || host.trim() === '') {
throw new BusinessError({
code: 401,
message: '代理服务器地址不能为空'
});
}
if (port < 1 || port > 65535) {
throw new BusinessError({
code: 402,
message: '端口号必须在1-65535范围内'
});
}
// 设置代理
connection.setAppHttpProxy(host, port, exclusions);
console.info(`代理设置成功: ${host}:${port}`);
console.info(`排除列表: ${exclusions.join(', ') || '无'}`);
} catch (error) {
const err = error as BusinessError;
console.error(`设置代理失败: ${err.code}, ${err.message}`);
throw err;
}
}
}
// 使用示例
export class ProxyExample {
async demonstrateProxyManagement(): Promise<void> {
try {
// 1. 设置代理
console.log('=== 步骤1:设置代理 ===');
ProxyManager.setHttpProxy('proxy.company.com', 8080, [
'internal.company.com',
'*.local'
]);
// 等待2秒
await this.delay(2000);
// 2. 取消代理(方案一)
console.log('\n=== 步骤2:取消代理(方案一)===');
ProxyManager.cancelAppHttpProxy();
// 3. 再次设置不同代理
console.log('\n=== 步骤3:设置新代理 ===');
ProxyManager.setHttpProxy('backup.proxy.com', 8888);
// 4. 再次取消
console.log('\n=== 步骤4:再次取消代理 ===');
ProxyManager.cancelAppHttpProxy();
} catch (error) {
console.error(`代理管理演示失败: ${error.message}`);
}
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
适用场景
-
完全取消代理:当应用不再需要任何代理时
-
网络环境切换:从公司网络切换到家庭网络
-
临时代理需求结束:安全扫描、测试抓包等临时需求完成后
注意事项
-
空字符串验证:必须使用空字符串
"",不能使用null或undefined -
端口为0:端口必须设置为
0,表示不使用代理端口 -
排除列表清空:排除列表必须设置为空数组
[] -
立即生效:设置后立即生效,无需重启应用
解决方案二:恢复默认网络配置
实现原理
通过获取当前网络的默认代理配置,然后将应用代理设置为该默认配置。这种方法更灵活,可以:
-
恢复系统默认代理设置
-
在不同网络间保持一致的代理策略
-
避免完全取消代理可能带来的网络访问问题
代码实现
import { connection } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
/**
* 方案二:恢复默认网络配置
* 适用于需要保持系统代理策略的场景
*/
class DefaultProxyManager {
private static currentProxyConfig: connection.HttpProxy | null = null;
/**
* 保存当前代理配置
*/
static async saveCurrentProxyConfig(): Promise<void> {
return new Promise((resolve, reject) => {
connection.getDefaultHttpProxy((err, proxyInfo) => {
if (err) {
console.error(`保存代理配置失败: ${err.code}, ${err.message}`);
reject(err);
return;
}
this.currentProxyConfig = proxyInfo;
console.info('当前代理配置已保存:', JSON.stringify(proxyInfo));
resolve();
});
});
}
/**
* 恢复为默认代理配置(方案二)
*/
static async restoreToDefaultProxy(): Promise<void> {
try {
// 获取默认网络代理配置
const defaultProxy = await this.getDefaultProxy();
// 设置为默认配置
connection.setAppHttpProxy(
defaultProxy.host,
defaultProxy.port,
defaultProxy.exclusionList
);
console.info('已恢复为默认代理配置:', JSON.stringify(defaultProxy));
// 验证恢复结果
await this.verifyRestoration(defaultProxy);
} catch (error) {
const err = error as BusinessError;
console.error(`恢复默认代理失败: ${err.code}, ${err.message}`);
throw err;
}
}
/**
* 获取默认代理配置
*/
private static getDefaultProxy(): Promise<connection.HttpProxy> {
return new Promise((resolve, reject) => {
connection.getDefaultHttpProxy((err, proxyInfo) => {
if (err) {
reject(err);
return;
}
resolve(proxyInfo);
});
});
}
/**
* 验证代理恢复结果
*/
private static async verifyRestoration(expectedProxy: connection.HttpProxy): Promise<void> {
const currentProxy = await this.getDefaultProxy();
if (currentProxy.host === expectedProxy.host &&
currentProxy.port === expectedProxy.port &&
JSON.stringify(currentProxy.exclusionList) === JSON.stringify(expectedProxy.exclusionList)) {
console.info('验证成功:代理配置已恢复为默认值');
} else {
console.warn(`验证警告:代理配置恢复不一致
期望: ${JSON.stringify(expectedProxy)}
实际: ${JSON.stringify(currentProxy)}`);
}
}
/**
* 智能代理管理:根据网络环境自动调整
*/
static async smartProxyManagement(): Promise<void> {
try {
// 获取当前网络类型
const netHandle = connection.getDefaultNet();
const netCapabilities = await this.getNetCapabilities(netHandle);
// 根据网络类型决定代理策略
if (netCapabilities.hasTransport(connection.NetCapabilities.TRANSPORT_WIFI)) {
console.log('检测到Wi-Fi网络,检查代理配置...');
// 获取Wi-Fi网络的默认代理
const wifiProxy = await this.getDefaultProxy();
if (wifiProxy.host && wifiProxy.port > 0) {
console.warn('检测到Wi-Fi网络已配置代理,应用将使用系统代理设置');
// 保持系统代理设置
} else {
console.log('Wi-Fi网络未配置代理,应用使用直连模式');
// 取消代理
connection.setAppHttpProxy('', 0, []);
}
} else if (netCapabilities.hasTransport(connection.NetCapabilities.TRANSPORT_CELLULAR)) {
console.log('检测到移动数据网络,建议取消代理以节省流量');
// 移动数据下取消代理
connection.setAppHttpProxy('', 0, []);
} else {
console.log('未知网络类型,使用默认代理策略');
await this.restoreToDefaultProxy();
}
} catch (error) {
console.error(`智能代理管理失败: ${error.message}`);
// 失败时恢复默认配置
await this.restoreToDefaultProxy();
}
}
/**
* 获取网络能力
*/
private static getNetCapabilities(netHandle: connection.NetHandle): Promise<connection.NetCapabilities> {
return new Promise((resolve, reject) => {
connection.getNetCapabilities(netHandle, (err, capabilities) => {
if (err) {
reject(err);
return;
}
resolve(capabilities);
});
});
}
}
// 使用示例
export class DefaultProxyExample {
async demonstrateDefaultProxyRestoration(): Promise<void> {
try {
// 1. 保存当前代理配置
console.log('=== 步骤1:保存当前代理配置 ===');
await DefaultProxyManager.saveCurrentProxyConfig();
// 2. 设置自定义代理
console.log('\n=== 步骤2:设置自定义代理 ===');
connection.setAppHttpProxy('custom.proxy.com', 9090, ['api.local']);
// 等待用户操作
console.log('自定义代理已设置,等待3秒...');
await this.delay(3000);
// 3. 恢复为默认配置
console.log('\n=== 步骤3:恢复为默认代理配置 ===');
await DefaultProxyManager.restoreToDefaultProxy();
// 4. 演示智能代理管理
console.log('\n=== 步骤4:智能代理管理演示 ===');
await DefaultProxyManager.smartProxyManagement();
} catch (error) {
console.error(`默认代理恢复演示失败: ${error.message}`);
}
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
适用场景
-
企业环境:恢复公司网络的默认代理设置
-
多网络切换:在不同网络环境间保持正确的代理策略
-
系统集成:需要与系统代理设置保持一致的应用
-
故障恢复:当自定义代理出现问题时恢复系统默认
注意事项
-
异步操作:
getDefaultHttpProxy是异步方法,需要使用回调或Promise -
网络绑定:如果应用绑定到特定网络,获取的是该网络的代理配置
-
配置一致性:确保恢复的配置与系统当前网络环境匹配
-
错误处理:网络不可用时需要适当的错误处理
完整实战示例
场景:企业VPN应用代理管理
下面是一个完整的企业VPN应用代理管理示例,结合了两种方案的优势:
import { connection } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
/**
* 企业VPN代理管理器
* 支持多种代理模式和智能切换
*/
export class EnterpriseProxyManager {
private proxyConfigs: Map<string, ProxyConfig> = new Map();
private currentMode: ProxyMode = ProxyMode.DIRECT;
// 代理模式枚举
static readonly ProxyMode = {
DIRECT: 'direct', // 直连模式
SYSTEM: 'system', // 系统代理
CUSTOM: 'custom', // 自定义代理
VPN: 'vpn' // VPN代理
};
constructor() {
this.initializeDefaultConfigs();
}
/**
* 初始化默认代理配置
*/
private initializeDefaultConfigs(): void {
// 公司内网代理
this.proxyConfigs.set('company', {
name: '公司内网代理',
host: 'proxy.company.com',
port: 8080,
exclusionList: [
'*.company.local',
'internal.api.com',
'192.168.*'
],
description: '公司内部网络代理,用于访问外部资源'
});
// 开发测试代理
this.proxyConfigs.set('development', {
name: '开发测试代理',
host: 'dev.proxy.com',
port: 8888,
exclusionList: [
'localhost',
'127.0.0.1',
'*.test'
],
description: '开发环境代理,用于调试和抓包'
});
// VPN代理
this.proxyConfigs.set('vpn', {
name: 'VPN安全代理',
host: 'vpn.secure.com',
port: 443,
exclusionList: [],
description: 'VPN加密通道,用于安全访问'
});
}
/**
* 切换代理模式
*/
async switchProxyMode(mode: string, configKey?: string): Promise<boolean> {
try {
console.log(`切换代理模式: ${mode}`);
switch (mode) {
case EnterpriseProxyManager.ProxyMode.DIRECT:
// 方案一:直连模式(取消代理)
return await this.setDirectMode();
case EnterpriseProxyManager.ProxyMode.SYSTEM:
// 方案二:系统代理模式
return await this.setSystemMode();
case EnterpriseProxyManager.ProxyMode.CUSTOM:
// 自定义代理模式
if (!configKey) {
throw new BusinessError({
code: 403,
message: '自定义模式需要指定配置键'
});
}
return await this.setCustomMode(configKey);
case EnterpriseProxyManager.ProxyMode.VPN:
// VPN代理模式
return await this.setVpnMode();
default:
throw new BusinessError({
code: 404,
message: `不支持的代理模式: ${mode}`
});
}
} catch (error) {
console.error(`切换代理模式失败: ${error.message}`);
return false;
}
}
/**
* 设置直连模式(取消代理)
*/
private async setDirectMode(): Promise<boolean> {
try {
// 方案一:设置空代理配置
connection.setAppHttpProxy('', 0, []);
this.currentMode = EnterpriseProxyManager.ProxyMode.DIRECT;
console.info('已切换到直连模式(代理已取消)');
// 验证模式切换
await this.verifyCurrentMode();
return true;
} catch (error) {
console.error(`设置直连模式失败: ${error.message}`);
return false;
}
}
/**
* 设置系统代理模式
*/
private async setSystemMode(): Promise<boolean> {
try {
// 获取系统默认代理配置
const systemProxy = await this.getSystemProxy();
// 设置为系统配置
connection.setAppHttpProxy(
systemProxy.host,
systemProxy.port,
systemProxy.exclusionList
);
this.currentMode = EnterpriseProxyManager.ProxyMode.SYSTEM;
console.info('已切换到系统代理模式:', JSON.stringify(systemProxy));
await this.verifyCurrentMode();
return true;
} catch (error) {
console.error(`设置系统代理模式失败: ${error.message}`);
return false;
}
}
/**
* 设置自定义代理模式
*/
private async setCustomMode(configKey: string): Promise<boolean> {
const config = this.proxyConfigs.get(configKey);
if (!config) {
throw new BusinessError({
code: 405,
message: `未找到代理配置: ${configKey}`
});
}
try {
// 设置自定义代理
connection.setAppHttpProxy(
config.host,
config.port,
config.exclusionList
);
this.currentMode = EnterpriseProxyManager.ProxyMode.CUSTOM;
console.info(`已切换到自定义代理模式 [${config.name}]:`, {
host: config.host,
port: config.port,
exclusions: config.exclusionList.length
});
await this.verifyCurrentMode();
return true;
} catch (error) {
console.error(`设置自定义代理模式失败: ${error.message}`);
return false;
}
}
/**
* 设置VPN代理模式
*/
private async setVpnMode(): Promise<boolean> {
// 检查VPN连接状态
const vpnConnected = await this.checkVpnConnection();
if (!vpnConnected) {
const userConfirmed = await this.showVpnPrompt();
if (!userConfirmed) {
console.warn('用户取消VPN连接,保持当前模式');
return false;
}
}
return await this.setCustomMode('vpn');
}
/**
* 获取系统代理配置
*/
private getSystemProxy(): Promise<connection.HttpProxy> {
return new Promise((resolve, reject) => {
connection.getDefaultHttpProxy((err, proxyInfo) => {
if (err) {
reject(err);
return;
}
resolve(proxyInfo);
});
});
}
/**
* 验证当前代理模式
*/
private async verifyCurrentMode(): Promise<void> {
try {
const currentProxy = await this.getSystemProxy();
console.log('当前代理配置验证:');
console.log(`- 主机: ${currentProxy.host || '(空)'}`);
console.log(`- 端口: ${currentProxy.port || 0}`);
console.log(`- 排除域名: ${currentProxy.exclusionList?.length || 0}个`);
console.log(`- 当前模式: ${this.currentMode}`);
} catch (error) {
console.warn(`代理验证失败: ${error.message}`);
}
}
/**
* 检查VPN连接状态
*/
private async checkVpnConnection(): Promise<boolean> {
// 这里应该实现实际的VPN连接检查
// 简化实现,返回模拟值
return Math.random() > 0.5;
}
/**
* 显示VPN连接提示
*/
private async showVpnPrompt(): Promise<boolean> {
return new Promise((resolve) => {
promptAction.showToast({
message: '检测到VPN未连接,是否立即连接?',
duration: 3000,
bottom: '100vp'
});
// 简化实现,实际应该显示对话框让用户选择
setTimeout(() => {
resolve(true);
}, 1000);
});
}
/**
* 获取当前代理状态
*/
getCurrentStatus(): ProxyStatus {
return {
mode: this.currentMode,
configs: Array.from(this.proxyConfigs.keys()),
timestamp: new Date().toISOString()
};
}
/**
* 添加自定义代理配置
*/
addProxyConfig(key: string, config: ProxyConfig): void {
if (this.proxyConfigs.has(key)) {
console.warn(`代理配置 ${key} 已存在,将被覆盖`);
}
this.proxyConfigs.set(key, config);
console.info(`代理配置已添加: ${key} - ${config.name}`);
}
/**
* 移除代理配置
*/
removeProxyConfig(key: string): boolean {
const removed = this.proxyConfigs.delete(key);
if (removed) {
console.info(`代理配置已移除: ${key}`);
} else {
console.warn(`代理配置不存在: ${key}`);
}
return removed;
}
}
// 类型定义
interface ProxyConfig {
name: string;
host: string;
port: number;
exclusionList: string[];
description?: string;
}
interface ProxyStatus {
mode: string;
configs: string[];
timestamp: string;
}
type ProxyMode = 'direct' | 'system' | 'custom' | 'vpn';
// 使用示例
export class EnterpriseProxyExample {
private proxyManager: EnterpriseProxyManager;
constructor() {
this.proxyManager = new EnterpriseProxyManager();
}
async runCompleteDemo(): Promise<void> {
console.log('=== 企业代理管理器完整演示 ===\n');
try {
// 1. 显示初始状态
console.log('1. 初始状态:');
console.log(JSON.stringify(this.proxyManager.getCurrentStatus(), null, 2));
// 2. 切换到公司代理
console.log('\n2. 切换到公司代理模式:');
const success1 = await this.proxyManager.switchProxyMode(
EnterpriseProxyManager.ProxyMode.CUSTOM,
'company'
);
console.log(`切换结果: ${success1 ? '成功' : '失败'}`);
await this.delay(2000);
// 3. 切换到直连模式(取消代理)
console.log('\n3. 切换到直连模式(取消代理):');
const success2 = await this.proxyManager.switchProxyMode(
EnterpriseProxyManager.ProxyMode.DIRECT
);
console.log(`切换结果: ${success2 ? '成功' : '失败'}`);
await this.delay(2000);
// 4. 切换到系统代理模式
console.log('\n4. 切换到系统代理模式:');
const success3 = await this.proxyManager.switchProxyMode(
EnterpriseProxyManager.ProxyMode.SYSTEM
);
console.log(`切换结果: ${success3 ? '成功' : '失败'}`);
await this.delay(2000);
// 5. 添加新的代理配置
console.log('\n5. 添加新的代理配置:');
this.proxyManager.addProxyConfig('test', {
name: '测试环境代理',
host: 'test.proxy.com',
port: 9999,
exclusionList: ['*.test.local'],
description: '测试环境专用代理'
});
// 6. 切换到新配置
console.log('\n6. 切换到新配置:');
const success4 = await this.proxyManager.switchProxyMode(
EnterpriseProxyManager.ProxyMode.CUSTOM,
'test'
);
console.log(`切换结果: ${success4 ? '成功' : '失败'}`);
// 7. 显示最终状态
console.log('\n7. 最终状态:');
console.log(JSON.stringify(this.proxyManager.getCurrentStatus(), null, 2));
console.log('\n=== 演示完成 ===');
} catch (error) {
console.error(`演示过程中出错: ${error.message}`);
}
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
常见问题解答(FAQ)
Q1:如何获取设备当前的代理列表?
A:通过connection.getDefaultHttpProxyAPI可以获取当前网络的代理配置信息。如果需要获取所有网络的代理配置,需要结合connection.getAllNets遍历所有网络接口。
async function getAllNetworkProxies(): Promise<Map<string, connection.HttpProxy>> {
const proxyMap = new Map<string, connection.HttpProxy>();
try {
// 获取所有网络
const nets = connection.getAllNets();
for (const net of nets) {
const proxy = await getProxyForNet(net);
proxyMap.set(net.netId.toString(), proxy);
}
} catch (error) {
console.error(`获取网络代理失败: ${error.message}`);
}
return proxyMap;
}
function getProxyForNet(netHandle: connection.NetHandle): Promise<connection.HttpProxy> {
return new Promise((resolve, reject) => {
connection.getDefaultHttpProxy(netHandle, (err, proxyInfo) => {
if (err) {
reject(err);
return;
}
resolve(proxyInfo);
});
});
}
Q2:如何检测Wi-Fi代理并阻止?
A:可以通过检测当前网络类型和代理配置来实现智能阻止:
class ProxyBlocker {
/**
* 检测并阻止Wi-Fi代理
*/
static async detectAndBlockWifiProxy(): Promise<boolean> {
try {
// 获取当前网络
const netHandle = connection.getDefaultNet();
const capabilities = await this.getNetCapabilities(netHandle);
// 检查是否为Wi-Fi网络
if (!capabilities.hasTransport(connection.NetCapabilities.TRANSPORT_WIFI)) {
console.log('当前不是Wi-Fi网络,无需检测代理');
return false;
}
// 获取代理配置
const proxyInfo = await this.getProxyInfo();
// 检查是否设置了代理
if (proxyInfo.host && proxyInfo.port > 0) {
console.warn('检测到Wi-Fi网络已配置代理');
// 显示警告并询问用户
const userChoice = await this.showProxyWarning(proxyInfo);
if (userChoice === 'block') {
// 用户选择阻止,取消代理
connection.setAppHttpProxy('', 0, []);
console.info('已阻止Wi-Fi代理');
return true;
} else if (userChoice === 'allow') {
// 用户允许使用代理
console.info('用户允许使用代理');
return false;
} else {
// 用户取消,保持原样
console.info('用户取消操作');
return false;
}
}
return false;
} catch (error) {
console.error(`代理检测失败: ${error.message}`);
return false;
}
}
/**
* 显示代理警告
*/
private static async showProxyWarning(proxyInfo: connection.HttpProxy): Promise<'block' | 'allow' | 'cancel'> {
// 实际应用中应该显示对话框让用户选择
// 这里简化为控制台提示
console.warn(`
⚠️ 安全警告:检测到Wi-Fi代理配置
代理服务器: ${proxyInfo.host}:${proxyInfo.port}
排除域名: ${proxyInfo.exclusionList?.join(', ') || '无'}
请确认是否信任此代理服务器:
1. 阻止代理(推荐)
2. 允许使用代理
3. 取消操作
`);
// 模拟用户选择(实际应该等待用户输入)
return 'block';
}
}
Q3:为何无论connection.setAppHttpProxy设置的域名是否正确,都会返回成功?
A:connection.setAppHttpProxy接口仅负责将代理配置写入系统,不会验证代理服务器的可用性。这是设计上的考虑:
-
性能考虑:验证代理可用性需要网络请求,会增加延迟
-
灵活性:允许设置暂时不可用的代理(如服务器维护中)
-
异步验证:应用可以在设置后自行验证代理可用性
建议的验证方案:
class ProxyValidator {
/**
* 验证代理服务器可用性
*/
static async validateProxy(host: string, port: number, timeout: number = 5000): Promise<boolean> {
return new Promise((resolve) => {
// 创建TCP连接测试
const socket = new net.Socket();
let isConnected = false;
// 设置超时
const timer = setTimeout(() => {
socket.destroy();
resolve(false);
}, timeout);
socket.on('connect', () => {
clearTimeout(timer);
isConnected = true;
socket.destroy();
resolve(true);
});
socket.on('error', (error) => {
clearTimeout(timer);
console.warn(`代理连接失败: ${error.message}`);
resolve(false);
});
socket.on('timeout', () => {
clearTimeout(timer);
socket.destroy();
resolve(false);
});
// 尝试连接
socket.connect(port, host);
});
}
/**
* 设置并验证代理
*/
static async setAndValidateProxy(host: string, port: number, exclusions: string[] = []): Promise<boolean> {
try {
// 1. 设置代理
connection.setAppHttpProxy(host, port, exclusions);
console.info(`代理已设置: ${host}:${port}`);
// 2. 验证代理可用性
console.info('正在验证代理可用性...');
const isValid = await this.validateProxy(host, port);
if (isValid) {
console.info('代理验证成功,服务器可用');
return true;
} else {
console.warn('代理验证失败,服务器可能不可用');
// 可选:自动取消无效代理
// connection.setAppHttpProxy('', 0, []);
// console.info('已自动取消无效代理');
return false;
}
} catch (error) {
console.error(`设置验证代理失败: ${error.message}`);
return false;
}
}
}
最佳实践建议
1. 代理配置管理策略
分级管理:
// 代理配置级别
enum ProxyPriority {
CRITICAL = 1, // 关键业务,必须使用代理
IMPORTANT = 2, // 重要业务,建议使用代理
NORMAL = 3, // 普通业务,根据网络决定
OPTIONAL = 4 // 可选业务,不使用代理
}
// 根据业务优先级决定代理策略
function determineProxyStrategy(priority: ProxyPriority, networkType: string): boolean {
const strategies = {
[ProxyPriority.CRITICAL]: {
wifi: true, // Wi-Fi下使用代理
cellular: true, // 移动数据下使用代理
ethernet: true // 有线网络下使用代理
},
[ProxyPriority.IMPORTANT]: {
wifi: true,
cellular: false, // 移动数据下不使用代理(节省流量)
ethernet: true
},
[ProxyPriority.NORMAL]: {
wifi: false, // 仅在公司网络使用代理
cellular: false,
ethernet: false
},
[ProxyPriority.OPTIONAL]: {
wifi: false,
cellular: false,
ethernet: false
}
};
return strategies[priority][networkType] || false;
}
2. 错误处理与重试机制
class RobustProxyManager {
private maxRetries = 3;
private retryDelay = 1000; // 1秒
/**
* 带重试的代理设置
*/
async setProxyWithRetry(host: string, port: number, exclusions: string[] = []): Promise<boolean> {
let retryCount = 0;
while (retryCount < this.maxRetries) {
try {
console.log(`尝试设置代理 (第${retryCount + 1}次): ${host}:${port}`);
// 设置代理
connection.setAppHttpProxy(host, port, exclusions);
// 验证设置是否成功
const isSet = await this.verifyProxySetting(host, port);
if (isSet) {
console.info(`代理设置成功: ${host}:${port}`);
return true;
} else {
throw new Error('代理设置验证失败');
}
} catch (error) {
retryCount++;
console.warn(`代理设置失败 (第${retryCount}次): ${error.message}`);
if (retryCount < this.maxRetries) {
console.log(`等待${this.retryDelay}ms后重试...`);
await this.delay(this.retryDelay);
// 指数退避
this.retryDelay *= 2;
}
}
}
console.error(`代理设置失败,已达到最大重试次数: ${this.maxRetries}`);
return false;
}
/**
* 验证代理设置
*/
private async verifyProxySetting(expectedHost: string, expectedPort: number): Promise<boolean> {
return new Promise((resolve) => {
connection.getDefaultHttpProxy((err, proxyInfo) => {
if (err) {
resolve(false);
return;
}
const isCorrect = proxyInfo.host === expectedHost &&
proxyInfo.port === expectedPort;
resolve(isCorrect);
});
});
}
}
3. 性能优化建议
-
延迟加载:代理配置在需要时才加载,避免启动时立即设置
-
缓存机制:缓存常用的代理配置,减少重复查询
-
批量操作:多个代理变更合并执行,减少系统调用
-
异步验证:代理验证在后台线程执行,不阻塞主线程
4. 安全注意事项
-
敏感信息保护:代理密码等敏感信息应加密存储
-
配置验证:用户输入的代理配置需要严格验证
-
权限控制:代理设置功能需要适当的用户权限
-
日志记录:记录代理变更操作,便于审计和故障排查
总结
通过本文的详细讲解,我们深入探讨了HarmonyOS 6中connection.setAppHttpProxy设置代理后如何取消代理的两种解决方案:
核心解决方案对比
|
方案 |
方法 |
适用场景 |
优点 |
缺点 |
|---|---|---|---|---|
|
方案一 |
设置空代理配置 |
完全取消代理,恢复直连 |
简单直接,立即生效 |
可能丢失系统代理配置 |
|
方案二 |
恢复默认配置 |
保持系统代理策略 |
更灵活,保持一致性 |
需要获取当前网络配置 |
关键要点
-
方案选择:根据具体业务需求选择合适的取消代理方案
-
错误处理:完善的错误处理机制确保代理配置的可靠性
-
网络感知:结合网络状态智能管理代理配置
-
用户体验:提供清晰的代理状态反馈和操作确认
扩展思考
在实际开发中,还可以考虑以下扩展功能:
-
代理自动发现:实现WPAD协议自动发现代理配置
-
代理负载均衡:多个代理服务器之间的智能切换
-
代理健康检查:定期检查代理服务器可用性
-
代理规则引擎:基于URL、内容类型等的智能代理规则
通过合理使用HarmonyOS的网络代理API,开发者可以构建出既安全又高效的企业级网络应用,满足各种复杂的网络环境需求。
更多推荐

所有评论(0)