OkHttp PublicSuffix包的后缀列表处理

PublicSuffixDatabase.list 是公共后缀列表(Public Suffix List,PSL)的文件之一,以下是 PublicSuffixDatabase.list 文件及一些常见的开源处理库的介绍:

PublicSuffixDatabase.list 文件

  • 概念 :公共后缀列表是一个包含所有已知公共后缀的列表,它定义了互联网上用户可以注册的域名后缀范围,这些后缀是域名体系中的公共部分,例如.com、.cn、.co.uk 等。
  • 作用 :最初是为了满足浏览器制造商的需求而创建,用于帮助浏览器解决如避免为高级域名后缀设置破坏隐私的"supercookies"、突出显示用户界面中域名最重要的部分、按站点准确排序历史记录条目等问题。现在,它已成为互联网域名管理的一项重要资源,广泛应用于网络安全、域名解析、Cookie 管理等诸多领域。
  • 维护 :由 Mozilla 发起并维护,作为社区资源,由志愿者提交和更新数据,以确保其准确性和时效性。
  • 格式 :它是一个纯文本文件,每行定义一个规则。规则主要分为三类,一类是普通规则,如 ".com" 表示所有以.com 结尾的域名都属于公共后缀;一类是以 "!" 开头的例外规则,用于表示某些特定的域名虽然符合公共后缀的规则,但实际上是可注册的域名,如 "!example.com" 表示 example.com 是一个可注册的域名,而不是公共后缀;还有一类是以 "." 开头的通配符规则,用于表示某个域及其所有子域都属于公共后缀,如 ".example.com" 表示所有以.example.com 结尾的域名都是公共后缀。

开源处理库

以下是部分常见的开源处理库:

PublicSuffixList JavaScript 版本

  • 特性 :提供了一个简单易用的接口,可以快速判断一个域名是否属于公共后缀,并且能够解析域名的各个组成部分,如注册域、子域等。它遵循公共后缀列表的格式和规则,确保了域名解析的准确性和一致性。体积小巧,性能高效,适合在各种 JavaScript 环境中使用,包括浏览器和 Node.js。
  • 安装 :npm install public-suffix-list
  • 使用方法
    • 导入模块:const { PublicSuffixList } = require('public-suffix-list')
    • 创建实例并加载默认的公共后缀列表:const psl = new PublicSuffixList() 或者 const psl = PublicSuffixList.getDefault()
    • 使用方法判断域名是否有效、解析域名等,如 psl.isValid('example.com') 判断域名是否有效,psl.parse('www.example.co.uk') 解析域名结构。

PublicSuffixList Ruby 版本

  • 特性 :提供了丰富的功能,可以方便地判断域名是否符合公共后缀列表规则、解析域名的各个部分等。它具有良好的可读性和可维护性,便于开发者理解和使用。并且,它可以与其他 Ruby 库无缝集成,方便在 Ruby 项目中进行域名处理。
  • 安装 :gem install public_suffix
  • 使用方法
    • 需要先加载公共后缀列表,可以通过 PublicSuffix::List.default 获取默认的列表。
    • 然后可以使用 PublicSuffix::Domain.new(domain, list: list) 创建一个域名对象,进而调用其方法来获取域名的各个部分,如 domain.tld 获取顶级域,domain.sld 获取二级域等。

PublicSuffix Python 版本

  • 特性 :提供了简单易用的 API,可以方便地判断域名是否有效、解析域名的各个组成部分等。它具有良好的兼容性,能够与 Python 的其他网络库和工具无缝配合使用。同时,它的性能也较为出色,能够快速处理大量的域名数据。
  • 安装 :pip install publicsuffixlist
  • 使用方法
    • 导入模块:from publicsuffixlist import PublicSuffixList
    • 创建公共后缀列表对象:psl = PublicSuffixList()
    • 使用方法判断域名是否有效、解析域名等,如 psl.privatesuffix(domain) 判断域名是否为私有后缀,psl.get_public_suffix(domain) 获取域名的公共后缀。

PublicSuffix Go 版本

  • 特性 :具有高性能和高并发处理能力,能够快速处理大量的域名数据。它的代码结构清晰,易于理解和使用,并且提供了丰富的文档和示例,方便开发者快速上手。同时,它也遵循公共后缀列表的最新规范,确保了域名解析的准确性和一致性。
  • 安装 :go get github.com/xeipuuv/go-publicsuffix
  • 使用方法
    • 导入包:import "github.com/xeipuuv/go-publicsuffix"
    • 使用函数如 publicsuffix.List.DomainInfo(domain) 来获取域名的注册管理机构信息,包括注册域、公共后缀等。

PublicSuffix PHP 版本

  • 特性 :提供了一个简单易用的接口,可以方便地判断域名是否符合公共后缀列表规则、解析域名的各个组成部分等。它与 PHP 的其他网络库和工具具有良好的兼容性,能够方便地集成到现有的 PHP 项目中。同时,它的代码也较为简洁,易于维护和扩展。
  • 安装 :通过 Composer 安装,composer require "ிலவு/public-suffix"
  • 使用方法
    • 导入类:use Ilav\PublicSuffix\PublicSuffix;
    • 创建公共后缀对象:$publicSuffix = new PublicSuffix;
    • 使用方法如 $publicSuffix->getPublicSuffix('www.example.com') 获取域名的公共后缀。

OkHttp 的 PublicSuffix 包是一个可以用于处理公共后缀列表的 Kotlin 版本的开源库,其具体介绍如下:

基本情况

OkHttp 是一个流行的 HTTP 客户端库,它提供了对 HTTP 请求和响应的高效处理,而其中的 PublicSuffix 包则是专门用于处理公共后缀相关问题的。

主要功能

  • 域名解析 :可以获取域名的有效顶级域名加一(Effective TLD Plus One),即注册域名,例如对于域名 "www.example.com",其有效顶级域名加一是 "example.com";对于 "shop.example.co.uk",有效顶级域名加一是 "example.co.uk"。
  • 同源策略支持 :帮助确定哪些域名应被视为 "同源",这对于确保网络安全、进行跨域资源共享(CORS)决策等非常重要。
  • 防止安全漏洞 :可阻止潜在的会话固定攻击、减少跨站请求伪造(CSRF)风险等,有助于提高网络应用的安全性。

使用方法

  • 引入库 :在项目中添加 OkHttp 的依赖,即可引入其 PublicSuffix 包。
  • 获取 PublicSuffixDatabase 对象 :通过 PublicSuffixDatabase.get() 方法获取一个 PublicSuffixDatabase 对象。
  • 解析域名 :调用 PublicSuffixDatabase 对象的 getEffectiveTldPlusOne(domain) 方法,传入需要解析的域名,即可得到该域名的有效顶级域名加一。

跨平台设计优势

  • 代码复用与平台特化的平衡 :OkHttp 的 PublicSuffix 包采用了 Kotlin Multiplatform 架构,核心逻辑在共享代码中实现,平台特定代码仅处理资源加载等平台差异,实现了 75% 的代码复用。
  • 统一 API :所有平台使用相同的接口,通过 PublicSuffixList.Default 提供统一访问点,方便开发者在不同平台上以一致的方式使用该库。
  • 可扩展性 :可以轻松添加新平台支持,且平台特定优化不影响其他平台。
  • 维护性 :平台特定代码与通用代码分离,关注点分离,便于维护。
  • 性能优化 :具有延迟加载、并发处理、中断处理等性能优化措施,确保数据只在需要时加载,减少内存占用,并保证数据加载的正确性和效率。

使用示例

使用 OkHttp 中的 PublicSuffix 包来获取域名的有效顶级域名加一的代码示例如下:

kotlin 复制代码
val domain1 = "www.example.com"
val result1 = PublicSuffixDatabase.get().getEffectiveTldPlusOne(domain1)
println(result1) // 输出 example.com

val domain2 = "shop.example.co.uk"
val result2 = PublicSuffixDatabase.get().getEffectiveTldPlusOne(domain2)
println(result2) // 输出 example.co.uk

val domain3 = "com"
val result3 = PublicSuffixDatabase.get().getEffectiveTldPlusOne(domain3)
println(result3) // 输出 null

OkHttp PublicSuffix的后缀列表处理源码分析

1. 整体域名解析流程

此图展示了从输入域名到最终获取有效顶级域名加一级域名(eTLD+1)的完整流程。

流程图

flowchart TD A([开始]) --> B[输入域名] B --> C[转换为 Unicode] C --> D[拆分标签] D --> E[匹配公共后缀规则] E --> F{公共后缀?} F -->|是| G[返回 null] F -->|否| H{异常规则?} H -->|是| I[偏移量=标签数-规则长度] H -->|否| J[偏移量=标签数-规则长度-1] I --> K[拆分原始标签] J --> K K --> L[截取标签] L --> M[拼接 eTLD+1] M --> N[返回结果] G --> O([结束]) N --> O class A,O startend class B,C,D,E,I,J,K,L,M process class F,H decision class G,N result classDef startend fill:#2,stroke:#BE8FED,stroke-width:2px classDef process fill:#5,stroke:#73A6FF,stroke-width:2px classDef decision fill:#6,stroke:#FFBC52,stroke-width:2px,shape:diamond classDef result fill:#8,stroke:#4CAF50,stroke-width:2px

解释

  1. 输入域名后,先将其转换为 Unicode 格式,再拆分成标签列表。
  2. 查找匹配的公共后缀规则,判断该域名是否为公共后缀,若是则直接返回 null
  3. 若不是公共后缀,判断规则是否为异常规则,根据不同情况计算首个标签偏移量。
  4. 按原始域名拆分标签列表,从偏移量位置开始截取标签并连接成字符串,最终返回 eTLD+1。

时序图

sequenceDiagram participant Client participant PublicSuffixDatabase participant PublicSuffixList Client->>PublicSuffixDatabase: getEffectiveTldPlusOne(domain) PublicSuffixDatabase->>PublicSuffixDatabase: 将域名转换为 Unicode PublicSuffixDatabase->>PublicSuffixDatabase: 拆分域名成标签列表 PublicSuffixDatabase->>PublicSuffixDatabase: findMatchingRule(domainLabels) PublicSuffixDatabase->>PublicSuffixList: ensureLoaded() PublicSuffixList-->>PublicSuffixDatabase: 列表已加载 PublicSuffixDatabase->>PublicSuffixList: bytes.binarySearch(...) PublicSuffixList-->>PublicSuffixDatabase: 匹配规则 PublicSuffixDatabase->>PublicSuffixDatabase: 判断域名是否为公共后缀 alt 域名是公共后缀 PublicSuffixDatabase-->>Client: null else 域名不是公共后缀 PublicSuffixDatabase->>PublicSuffixDatabase: 判断规则是否为异常规则 PublicSuffixDatabase->>PublicSuffixDatabase: 计算首个标签偏移量 PublicSuffixDatabase->>PublicSuffixDatabase: 按原始域名拆分标签列表 PublicSuffixDatabase->>PublicSuffixDatabase: 从偏移量位置开始截取标签列表 PublicSuffixDatabase->>PublicSuffixDatabase: 将截取的标签列表用点连接 PublicSuffixDatabase-->>Client: eTLD+1 end

解释

  1. 客户端调用 PublicSuffixDatabasegetEffectiveTldPlusOne 方法。
  2. PublicSuffixDatabase 进行域名转换、拆分标签列表等操作,调用 findMatchingRule 方法查找匹配规则。
  3. findMatchingRule 方法中会调用 PublicSuffixListensureLoaded 方法确保列表已加载,再通过 binarySearch 方法查找匹配规则。
  4. 根据匹配规则判断域名是否为公共后缀,若不是则计算偏移量并处理标签列表,最终将结果返回给客户端。

2. 规则匹配逻辑细节

该图详细展示了查找匹配规则时,精确匹配、通配符匹配和异常匹配的处理顺序。

flowchart TD classDef startend fill:#4,stroke:#BE8FED,stroke-width:2px; classDef process fill:#5,stroke:#73A6FF,stroke-width:2px; classDef decision fill:#6,stroke:#FFBC52,stroke-width:2px; A(开始查找规则):::process --> B(尝试精确匹配):::process B --> C{是否找到精确匹配?}:::decision C -->|是| D(记录精确匹配规则):::process C -->|否| E(尝试通配符匹配):::process D --> F(尝试异常匹配):::process E --> F F --> G{是否找到异常匹配?}:::decision G -->|是| H(使用异常匹配规则):::process G -->|否| I{精确匹配和通配符匹配哪个规则更长?}:::decision I -->|精确匹配长| J(使用精确匹配规则):::process I -->|通配符匹配长| K(使用通配符匹配规则):::process I -->|都未匹配| L(使用默认规则):::process H --> M(结束查找):::process J --> M K --> M L --> M

解释

  • 先进行精确匹配,若找到则记录该规则。
  • 若未找到精确匹配,进行通配符匹配。
  • 不管精确匹配是否成功,都尝试异常匹配。
  • 若找到异常匹配,优先使用该规则;否则比较精确匹配和通配符匹配规则的长度,使用较长的规则;若都未匹配,则使用默认规则。

3. 多段式后缀处理示例

www.example.co.uk 为例,展示如何处理多段式公共后缀。

graph LR classDef box fill:#f9f,stroke:#333,stroke-width:2px,color:#FFF classDef circle fill:#6f0,stroke:#FA0,stroke-width:2px,rx:15px A[[输入域名]]:::box --> B{拆分标签} B --> C{{识别后缀}}:::circle C --> D[计算eTLD+1] D --> E[[example.co.uk]]

解释

  • 输入域名被拆分成标签列表。
  • 查找规则时发现 co.uk 是公共后缀。
  • 根据规则计算出 eTLD+1 为 example.co.uk 并输出。

通过这些图,你可以更直观地理解公共后缀列表处理的核心逻辑和关键步骤。

相关推荐
Lei活在当下2 小时前
【业务场景架构实战】7. 多代智能手表适配:Android APP 表盘编辑页的功能驱动设计
android·设计模式·架构
手机不死我是天子6 小时前
《Android 核心组件深度系列 · 第 2 篇 Service》
android
前行的小黑炭6 小时前
Compose页面切换的几种方式:Navigation、NavigationBar+HorizontalPager,会导致LaunchedEffect执行?
android·kotlin·app
前行的小黑炭7 小时前
Android :Comnpose各种副作用的使用
android·kotlin·app
BD_Marathon21 小时前
【MySQL】函数
android·数据库·mysql
西西学代码21 小时前
安卓开发---耳机的按键设置的UI实例
android·ui
maki0771 天前
虚幻版Pico大空间VR入门教程 05 —— 原点坐标和项目优化技巧整理
android·游戏引擎·vr·虚幻·pico·htc vive·大空间
千里马学框架1 天前
音频焦点学习之AudioFocusRequest.Builder类剖析
android·面试·智能手机·车载系统·音视频·安卓framework开发·audio
fundroid1 天前
掌握 Compose 性能优化三步法
android·android jetpack
TeleostNaCl1 天前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea