npm.io
0.1.0 • Published 4d ago

@mogody/react-native-tencent-httpdns

Licence
MIT
Version
0.1.0
Deps
0
Size
90 kB
Vulns
0
Weekly
0

@mogody/react-native-tencent-httpdns

@mogody/react-native-tencent-httpdns 为 React Native 应用接入腾讯云 HTTPDNS。它只改造 React Native 的原生 HTTP 网络层,让 fetch、XHR、axios、apisauce 等仍然使用带域名的 URL,同时在 Android/iOS 原生侧对指定域名走腾讯 HTTPDNS 解析。

包内支持腾讯 HTTPDNS 的三种查询模式:HTTPS、HTTP AES 加密、HTTP DES 加密。默认并推荐使用 HTTPS 模式。

安装

yarn add @mogody/react-native-tencent-httpdns

iOS 安装 Pods:

bundle exec pod install

启动时机

必须在 App 启动阶段尽早调用 install,并且要早于第一次 React Native 网络请求。

这里的网络请求包括 fetch、XHR、axios、apisauce,以及任何最终走 React Native HTTP 网络层的请求。Android 需要在 React Native 创建共享 OkHttpClient 之前注入 DNS;iOS 需要在 React Native 创建 URLSession 之前设置 URLSession 配置提供者。

生产接入推荐优先使用原生启动期 API:Android 调用 TencentHttpDNS.installFromManifest(this),iOS 调用 MGTencentHttpDNSInstaller.installFromMainBundle()。JS install 仍可用于能保证调用足够早的场景。

不要把 JS URL 替换成 IP

JavaScript 侧的请求 URL 必须继续使用域名:

await fetch('https://api.example.com/v1/profile');

不要改成 IP,也不要在 JS 请求层手动拼 IP:

// 不要这样做
await fetch('https://203.0.113.10/v1/profile');

保持域名可以让 TLS 证书、SNI、Host、Cookie、重定向和原生 HTTPDNS 域名匹配都按预期工作。

hosts 白名单

hosts 是 HTTPDNS 域名白名单,只填写主机名,不包含协议、路径或端口。

hosts: ['api.example.com', 'static.example.com']

只有白名单内的域名会尝试使用腾讯 HTTPDNS;未列入 hosts 的域名会继续使用系统 DNS。建议只加入自己可控、已经在腾讯 HTTPDNS 后台配置好的业务域名。

支持的模式

channel 凭据 Android SDK 调用 iOS encryptType 说明
https token https() 2 HTTPS 查询模式,默认值,推荐用于公开项目和默认接入。
aes dnsKey aesHttp() 1 基于 HTTP 的 AES 加密查询模式。
des dnsKey desHttp() 0 基于 HTTP 的 DES 加密查询模式。

省略 channel 时等同于 channel: 'https'

用法示例

HTTPS 模式
import TencentHttpDNS from '@mogody/react-native-tencent-httpdns';

const result = await TencentHttpDNS.install({
  enabled: true,
  channel: 'https',
  dnsId: 'your-dns-id',
  token: 'your-https-token',
  hosts: ['api.example.com'],
  timeoutMs: 2000,
});
HTTPS 默认模式
import TencentHttpDNS from '@mogody/react-native-tencent-httpdns';

await TencentHttpDNS.install({
  dnsId: 'your-dns-id',
  token: 'your-https-token',
  hosts: ['api.example.com'],
});
AES 模式
import TencentHttpDNS from '@mogody/react-native-tencent-httpdns';

await TencentHttpDNS.install({
  channel: 'aes',
  dnsId: 'your-dns-id',
  dnsKey: 'your-dns-key',
  hosts: ['api.example.com'],
});
DES 模式
import TencentHttpDNS from '@mogody/react-native-tencent-httpdns';

await TencentHttpDNS.install({
  channel: 'des',
  dnsId: 'your-dns-id',
  dnsKey: 'your-dns-key',
  hosts: ['api.example.com'],
});
禁用模式
import TencentHttpDNS from '@mogody/react-native-tencent-httpdns';

await TencentHttpDNS.install({ enabled: false });

禁用模式不需要 dnsIdtokendnsKeychannelhosts,也不会调用原生安装逻辑。返回结果会包含 installed: falsereason: 'disabled'

Android 原生启动期安装

Android 如果需要抢在 React Native 共享 OkHttpClient 创建前安装 HTTPDNS,可以在 MainApplication.onCreate() 里调用包提供的原生 API:

import com.mogody.tencenthttpdns.TencentHttpDNS

override fun onCreate() {
  super.onCreate()
  TencentHttpDNS.installFromManifest(this)
  loadReactNative(this)
}

配置值由宿主 App 的 android/gradle.properties 提供,包内 AndroidManifest 会通过 manifest placeholders 合并成 meta-data

TENCENT_HTTPDNS_CHANNEL=https
TENCENT_HTTPDNS_DNS_ID=your-dns-id
TENCENT_HTTPDNS_HTTPS_TOKEN=your-https-token
TENCENT_HTTPDNS_AES_KEY=your-aes-key
TENCENT_HTTPDNS_DES_KEY=your-des-key
TENCENT_HTTPDNS_HOSTS=api.example.com,static.example.com

TENCENT_HTTPDNS_CHANNEL 支持 httpsaesdeshttps 使用 TENCENT_HTTPDNS_HTTPS_TOKENaes 使用 TENCENT_HTTPDNS_AES_KEYdes 使用 TENCENT_HTTPDNS_DES_KEY

iOS 原生启动期安装

iOS 如果需要抢在 React Native 创建 URLSession 前安装 HTTPDNS,可以在 AppDelegate.swift 里调用包提供的原生 API:

window = UIWindow(frame: UIScreen.main.bounds)

MGTencentHttpDNSInstaller.installFromMainBundle()

factory.startReactNative(
  withModuleName: "YourApp",
  in: window,
  launchOptions: launchOptions
)

Swift 工程需要在 bridging header 中导入 installer:

#import <MogodyTencentHttpDNS/MGTencentHttpDNSInstaller.h>

配置值由宿主 App 的 Info.plist 提供。建议把敏感值写成 Xcode Build Settings 占位符,再由本地或 CI 注入:

<key>TencentHTTPDNSChannel</key>
<string>https</string>
<key>TencentHTTPDNSDebug</key>
<false/>
<key>TencentHTTPDNSDnsId</key>
<string>$(TENCENT_HTTPDNS_DNS_ID)</string>
<key>TencentHTTPDNSHosts</key>
<string>api.example.com,static.example.com</string>
<key>TencentHTTPDNSHttpsToken</key>
<string>$(TENCENT_HTTPDNS_HTTPS_TOKEN)</string>

installFromMainBundle() 会默认使用 channel=httpstimeoutMs=2000debug=falseuseExpiredIp=falsepersistentCache=truebypassWhenProxy=true。如果 $(...) 占位符没有被 Xcode 替换,包内会把它视为空值并输出 HTTPDNS install skipped: missing bundle config

install 返回值

install 返回:

type TencentHttpDNSInstallResult = {
  installed: boolean;
  reason?: string;
  hosts: string[];
  platform: string;
};

已知的非异常原因:

reason 平台 含义
disabled JS 调用了 { enabled: false },未执行原生安装。
okhttp-client-already-created Android install 调用太晚,React Native 已缓存的共享 OkHttpClient 已经创建,现有客户端不会使用新 DNS。部分 React Native 版本会创建未缓存的 context client,因此 Android 生产接入应优先使用原生启动期安装。
proxy-detected iOS bypassWhenProxytrue 且检测到 HTTP、HTTPS 或 SOCKS 代理,已绕过 HTTPDNS。

installed: false 不一定代表抛错;请同时检查 reason

Options

Option Type Required Default Description
enabled boolean true 设置为 false 时进入禁用模式,不需要凭据、模式或域名。
channel 'https' | 'aes' | 'des' 'https' 腾讯 HTTPDNS 查询模式。
dnsId string 启用时必填 腾讯云 HTTPDNS 授权 ID。
token string channel: 'https' 时必填 HTTPS 模式使用的腾讯 HTTPDNS token。
dnsKey string channel: 'aes''des' 时必填 AES/DES 模式使用的腾讯 HTTPDNS key。
hosts string[] 启用时必填 HTTPDNS 域名白名单,只写 hostname。
timeoutMs number 2000 腾讯 SDK 查询超时时间,单位毫秒。
debug boolean false 启用原生 SDK 调试日志。
useExpiredIp boolean false 允许腾讯 SDK 使用过期 IP 缓存。
persistentCache boolean true 启用腾讯 SDK 持久化 IP 缓存。
bypassWhenProxy boolean true 检测到本地代理时绕过 HTTPDNS,便于抓包和调试。

Android 注意事项

Android 使用腾讯 io.github.dnspod:httpdns-sdk:4.11.0,并通过 React Native 的 OkHttpClientProvider 注入自定义 OkHttp provider。

安装后,React Native 共享 OkHttpClient 的 Dns 会先检查 hosts 白名单:白名单内域名使用 MSDKDnsResolver 查询,未命中的域名回退到 Dns.SYSTEM。因此 JS URL 仍要保持域名形式,且只有 hosts 中的域名会被 HTTPDNS 处理。

Android 生产接入建议使用 MainApplication.onCreate() 中的 TencentHttpDNS.installFromManifest(this),并确保它早于 loadReactNative(this)。JS install 仍可用于配置较早的场景,但如果 React Native 已经创建网络模块或 context-specific OkHttpClient,已有客户端不会 retroactively 使用新 DNS,且部分 React Native 版本无法可靠检测这种状态。

如果 install 调用太晚且 React Native 已经创建可检测的共享 OkHttpClient,Android 会返回 installed: falsereason: 'okhttp-client-already-created'。此时已有客户端不会受本次安装影响,请把安装前移到原生启动期。

aesdes 是基于 HTTP 的加密查询模式。Android 9+ 及应用自定义 Network Security Config 可能限制明文 HTTP;如果必须使用 AES/DES,请确认应用的 cleartext traffic 策略允许腾讯 HTTPDNS SDK 的 HTTP 查询通道。默认推荐 https 模式以避免明文通道配置。

iOS 注意事项

iOS 使用 MSDKDns_C11MSDKDnsHttpMessageTools,并通过 RCTSetCustomNSURLSessionConfigurationProvider 为 React Native 的 URLSession 注入 HTTPDNS 处理能力。

生产接入建议在 AppDelegate 中、factory.startReactNative(...) 前调用 MGTencentHttpDNSInstaller.installFromMainBundle()。JS install 仍可用于能保证足够早调用的场景,但如果 URLSession 已经创建,旧 session 不会 retroactively 应用新的 HTTPDNS 配置。

安装时会调用腾讯 SDK 的域名劫持白名单配置,例如 WGSetHijackDomainArray(hosts),只有 hosts 中的域名会被 HTTPDNS 处理。请继续在 JS 请求里使用域名,不要改成 IP。

如果 bypassWhenProxytrue 且系统检测到 HTTP、HTTPS 或 SOCKS 代理,iOS 会返回 installed: falsereason: 'proxy-detected',并绕过 HTTPDNS,方便调试代理和抓包场景。

aesdes 是基于 HTTP 的加密查询模式,可能受到 iOS ATS 明文 HTTP 限制影响。如果必须使用 AES/DES,请按应用安全策略为腾讯 HTTPDNS 查询通道配置 ATS 例外;默认推荐 https 模式。

清理缓存

清理指定域名缓存:

import TencentHttpDNS from '@mogody/react-native-tencent-httpdns';

await TencentHttpDNS.clearCache(['api.example.com']);

不传参数会尝试清理原生 SDK 支持范围内的全部 HTTPDNS 缓存:

await TencentHttpDNS.clearCache();

作用范围限制

本包只影响 React Native HTTP 网络层。

它不会自动覆盖 WebView、AVPlayer、TrackPlayer、CDN 图片加载器、上传 SDK、原生第三方 SDK 自己发起的网络请求,也不覆盖 WebSocket。若这些模块也需要 HTTPDNS,需要分别接入对应模块或 SDK 的 DNS/网络配置能力。

接入文档

宿主 App 接入说明见 docs/consumer/zh-CN.md

安全建议

不要把 dnsIdtokendnsKey 提交到源码仓库。安全配置、CI Secret、原生构建配置或运行时配置注入可以让凭据不进入源码控制,但如果这些值被打进移动端包内,仍会随分发的 App 二进制一起交付,不能视为对终端用户保密。

公开项目和默认接入场景建议优先使用 https 模式。只有在腾讯 HTTPDNS 后台配置、业务兼容性和平台明文策略都确认后,才使用 aesdes 模式。