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
解释:
- 输入域名后,先将其转换为 Unicode 格式,再拆分成标签列表。
- 查找匹配的公共后缀规则,判断该域名是否为公共后缀,若是则直接返回
null
。 - 若不是公共后缀,判断规则是否为异常规则,根据不同情况计算首个标签偏移量。
- 按原始域名拆分标签列表,从偏移量位置开始截取标签并连接成字符串,最终返回 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
解释:
- 客户端调用
PublicSuffixDatabase
的getEffectiveTldPlusOne
方法。 PublicSuffixDatabase
进行域名转换、拆分标签列表等操作,调用findMatchingRule
方法查找匹配规则。findMatchingRule
方法中会调用PublicSuffixList
的ensureLoaded
方法确保列表已加载,再通过binarySearch
方法查找匹配规则。- 根据匹配规则判断域名是否为公共后缀,若不是则计算偏移量并处理标签列表,最终将结果返回给客户端。
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
并输出。
通过这些图,你可以更直观地理解公共后缀列表处理的核心逻辑和关键步骤。