主题设置新增「CDN 加速」:CDN 地址 + 白名单 + 黑名单,黑名单优先 #3

Closed
opened 2026-10-25 07:49:29 +00:00 by laoyang · 2 comments
Owner

需求

在主题设置里新增一个 CDN 加速 标签页,参考 CDN Enabler 插件做一个精简版。

只要三个配置项,不要更多

序号 配置项 作用
1 CDN 地址 替换后的前缀地址,如 https://cdn.example.com
2 白名单 哪些文件走 CDN。一行一条规则
3 黑名单 哪些文件不走 CDN。一行一条规则

匹配逻辑(用户原话整理)

  1. 先看黑名单。文件只要命中黑名单,就保持原地址,不再加 CDN 前缀。
  2. 黑名单没命中,再看白名单。命中白名单的,把地址前面的站点域名换成 CDN 地址。
  3. 黑名单优先级高于白名单。同一个文件两边都命中时,按黑名单处理(不加速)。
  4. 白名单要能按 文件类型、路径、或某个固定路径 来匹配。
  5. 白名单与黑名单都支持一行一条规则,规则要非常灵活。

期望的规则语法(本次确定)

一行一条,匹配对象是 URL 的路径部分(正则规则除外,它对完整 URL 匹配)。
# 或 ; 开头的行视为注释,空行忽略。

写法 例子 含义
全匹配 * 所有静态文件
扩展名 jpg / .jpg / *.jpg 扩展名是 jpg
扩展名列表 jpg,png,webp 或 .jpg .png 命中任一
路径前缀 /wp-content/uploads/(以 / 开头、不含 *) 路径以它开头
路径通配 */uploads/*、/wp-content/themes/*/assets/* shell 通配,* 可跨 /
路径子串 uploads、wp-content 路径里含这段文字
正则 ~\/\d{4}\/\d{2}\/~ 用 ~...~ 包裹,对完整 URL 做 preg_match

安全底线(不受规则影响,硬编码)

下面这些永远不改写,否则站点会被改坏:

  1. 以 / 结尾的地址(页面、栏目页)—— 改成 CDN 会导致导航跳到 CDN、404。
  2. .php / .html / .htm 等动态或页面类后缀。
  3. wp-admin、wp-login、wp-json、wp-cron 等后台与接口路径。
  4. 已经指向 CDN 的地址(避免重复加前缀)。
  5. 非本站域名的地址(外链图片、其他 CDN 的资源)。

白名单为空时的行为

视为「全部静态文件都走 CDN」。理由:与 CDN Enabler 一致(只填一个 CDN 地址就能用),
也符合"只想加速、不想逐条配规则"的常见用法。这条要写进后台说明文字里,避免误解。

验收标准

功能

  1. 后台出现第十二个标签页「CDN 加速」,里面恰好 3 个可填控件(CDN 地址、白名单、黑名单)。
  2. CDN 地址为空时,整站行为与升级前完全一致(零改写)。
  3. 只填 CDN 地址、两个名单留空 → 页面里的静态资源地址全部换成 CDN 前缀。
  4. 黑名单命中 → 该资源保持原地址,即使它符合白名单。
  5. 黑名单优先级高于白名单 → 两边都命中时不加速。
  6. 规则语法七种写法逐个能匹配、能拒绝。

改写正确性

  1. 只在 src / href / srcset / 内联样式 url() 等出现资源地址的地方生效,不改页面链接。
  2. 绝对地址、协议相对地址(//example.com/...)都能改;data: / mailto: / tel: / javascript: 不动。
  3. 带查询字符串的地址(如 a.css?ver=1.2)改写后查询串原样保留。
  4. 后台页面、REST 接口、feed、AJAX、预览、定制器里都不改写。

不破坏既有能力

  1. 十一个已有标签页的顺序、内容、分组小标题全部不变。
  2. 3.2.33 的两栏顶边对齐、3.2.32 的目录分组、3.2.29 的自定义代码,全部回归通过。
  3. 前台页面渲染出来的内容,除资源域名外一个字节都不变。

不改什么

  • 不动 ASSET_PATH 的既有语义(那是主题自身资源前缀,与本功能是两条独立的路径)。
  • 不动任何已有选项的 id、默认值、存库键。
  • 不引入新的数据库表或选项键(沿用 kratos 这一个 option)。
  • 不做缓存清除、不做预热、不接入任何服务商 API —— 只做地址改写。
## 需求 在主题设置里新增一个 **CDN 加速** 标签页,参考 CDN Enabler 插件做一个精简版。 ### 只要三个配置项,不要更多 | 序号 | 配置项 | 作用 | |---|---|---| | 1 | **CDN 地址** | 替换后的前缀地址,如 `https://cdn.example.com` | | 2 | **白名单** | 哪些文件走 CDN。一行一条规则 | | 3 | **黑名单** | 哪些文件**不走** CDN。一行一条规则 | ### 匹配逻辑(用户原话整理) 1. **先看黑名单**。文件只要命中黑名单,就**保持原地址**,不再加 CDN 前缀。 2. **黑名单没命中,再看白名单**。命中白名单的,把地址前面的站点域名换成 CDN 地址。 3. **黑名单优先级高于白名单**。同一个文件两边都命中时,按黑名单处理(不加速)。 4. 白名单要能按 **文件类型**、**路径**、或**某个固定路径** 来匹配。 5. 白名单与黑名单都支持**一行一条规则**,规则要**非常灵活**。 ### 期望的规则语法(本次确定) 一行一条,匹配对象是 URL 的路径部分(正则规则除外,它对完整 URL 匹配)。 `#` 或 `;` 开头的行视为注释,空行忽略。 | 写法 | 例子 | 含义 | |---|---|---| | 全匹配 | `*` | 所有静态文件 | | 扩展名 | `jpg` / `.jpg` / `*.jpg` | 扩展名是 jpg | | 扩展名列表 | `jpg,png,webp` 或 `.jpg .png` | 命中任一 | | 路径前缀 | `/wp-content/uploads/`(以 `/` 开头、不含 `*`) | 路径以它开头 | | 路径通配 | `*/uploads/*`、`/wp-content/themes/*/assets/*` | shell 通配,`*` 可跨 `/` | | 路径子串 | `uploads`、`wp-content` | 路径里含这段文字 | | 正则 | `~\/\d{4}\/\d{2}\/~` | 用 `~...~` 包裹,对完整 URL 做 `preg_match` | ### 安全底线(不受规则影响,硬编码) 下面这些**永远不改写**,否则站点会被改坏: 1. 以 `/` 结尾的地址(页面、栏目页)—— 改成 CDN 会导致导航跳到 CDN、404。 2. `.php` / `.html` / `.htm` 等动态或页面类后缀。 3. `wp-admin`、`wp-login`、`wp-json`、`wp-cron` 等后台与接口路径。 4. 已经指向 CDN 的地址(避免重复加前缀)。 5. 非本站域名的地址(外链图片、其他 CDN 的资源)。 ### 白名单为空时的行为 **视为「全部静态文件都走 CDN」**。理由:与 CDN Enabler 一致(只填一个 CDN 地址就能用), 也符合"只想加速、不想逐条配规则"的常见用法。这条要写进后台说明文字里,避免误解。 ## 验收标准 ### 功能 1. 后台出现第十二个标签页「CDN 加速」,里面恰好 3 个可填控件(CDN 地址、白名单、黑名单)。 2. CDN 地址为空时,整站行为与升级前**完全一致**(零改写)。 3. 只填 CDN 地址、两个名单留空 → 页面里的静态资源地址全部换成 CDN 前缀。 4. 黑名单命中 → 该资源保持原地址,即使它符合白名单。 5. 黑名单优先级高于白名单 → 两边都命中时不加速。 6. 规则语法七种写法逐个能匹配、能拒绝。 ### 改写正确性 7. 只在 `src` / `href` / `srcset` / 内联样式 `url()` 等出现资源地址的地方生效,**不改页面链接**。 8. 绝对地址、协议相对地址(`//example.com/...`)都能改;`data:` / `mailto:` / `tel:` / `javascript:` 不动。 9. 带查询字符串的地址(如 `a.css?ver=1.2`)改写后**查询串原样保留**。 10. 后台页面、REST 接口、feed、AJAX、预览、定制器里**都不改写**。 ### 不破坏既有能力 11. 十一个已有标签页的顺序、内容、分组小标题全部不变。 12. 3.2.33 的两栏顶边对齐、3.2.32 的目录分组、3.2.29 的自定义代码,全部回归通过。 13. 前台页面渲染出来的内容,除资源域名外**一个字节都不变**。 ## 不改什么 - 不动 `ASSET_PATH` 的既有语义(那是主题自身资源前缀,与本功能是两条独立的路径)。 - 不动任何已有选项的 id、默认值、存库键。 - 不引入新的数据库表或选项键(沿用 `kratos` 这一个 option)。 - 不做缓存清除、不做预热、不接入任何服务商 API —— 只做地址改写。
Author
Owner

3.2.34 已发布

版本已发到 theme-update/,后台「主题设置」里能看到「CDN 加速」标签页(在「邮件通知」之后、「自定义代码」之前)。

落地形态

按需求只做了三样,没有加启用开关:

项 类型 说明
CDN 地址 单行文本,带 placeholder 留空 = 整个功能关闭,前台零变化
白名单 等宽多行框(10 行) 命中才加速;留空 = 全部静态文件都加速
黑名单 等宽多行框(10 行) 命中就不加速;优先级高于白名单

之所以不另加「启用」勾选框:那会多出一种半配置状态(勾了启用、地址忘填),看着是开着的、实际毫无效果。把「填了才生效」写进逻辑,省掉一次误判。

规则写法(一行一条,按字面形态自动识别,不用记语法)

*                       全部静态文件
jpg  /  .jpg  /  *.jpg   按扩展名
jpg,png,webp            一串扩展名,命中任一
/wp-content/uploads/    以这个路径开头
*/uploads/*             通配符,* 可跨斜杠
uploads                 路径里含这几个字
~\/20\d\d\/\d\d\/~      正则,对完整地址匹配
# 或 ; 开头              注释

有一个歧义必须专门解决

jpg 和 uploads 在字面上都是「一串纯字母」,分不出谁是扩展名、谁是路径片段。若一律当扩展名,uploads 这条会完全失效,而且没有任何提示 —— 用户只会看到"规则没反应",最难查。

处理办法:单个词同时按两种含义匹配(jpg 按扩展名命中 .jpg 文件;uploads 按路径子串命中 /wp-content/uploads/ 下的文件)。两个含义天然互斥,同时挂上不产生歧义。多个词(jpg,png)只按扩展名列表处理。

硬性排除(两套名单都改不了,因为改坏的方式极其致命)

  • 以斜杠结尾的地址(页面/栏目页/导航)→ 改了访客点导航跳到 CDN 域名,全站 404
  • 页面与动态后缀:php / html / htm / asp / jsp 等
  • 没有后缀的地址(接口、短链、伪静态页)
  • 后台与接口路径:wp-admin、wp-login.php、wp-json、wp-cron.php、xmlrpc.php、/feed/
  • 非本站域名(外链、别人家的 CDN)
  • 非 http(s) 协议:data: / mailto: / tel: / javascript:

后台、REST、AJAX、feed、WP-Cron、定制器预览、命令行一律不改写(后台改了会导致编辑器里看不到真实图片,REST 返回的地址与库对不上)。

?ver= 这类查询串原样保留 —— 丢了浏览器会一直吃 CDN 上的旧缓存,改了样式前台看不见,是这类功能最常见的事故。

站点装在子目录(example.com/blog/...)时,判规则用完整路径、拼 CDN 时剥掉子目录,所以规则照原路径写就行,不用为子目录改一遍。

验证

探针 结果
逻辑探针(十组判据:前置/地址写法/七种白名单/黑名单优先/硬性排除/域名/幂等/整页/子目录/正则卫生) 92 / 0
逻辑反向验证(M1M15 逐条注入 + E1E3 等价重写) 21 / 0
后台探针(真实渲染 + 几何 + 类型 + 说明块,宽窄屏) 56 / 0
后台反向验证(A1A12 注入 + E1E2 等价重写) 15 / 0
包契约(版本/函数/顺序/三控件/三说明/安全底线/缓冲/源码卫生) 69 / 0
包契约反向验证(改 zip 内字节,不改源码) 23 / 0
旧探针回归 toc330 101/0 · admin330 88/0 · admin328 13/0 · pkgcheck331/332/333 全绿 · e2e322/323 通过

反向验证过程中抓出三处真实盲点(不是产品 bug,是我的判据不够):

  1. data: 协议排除:原用例 data:image/png;base64,... 经 parse_url 后没有扩展名,被「无扩展名」那条顺带挡住了 ⇒ 拆掉协议排除也仍绿。补了一条带扩展名的 data:image/png;base64.a.jpg,只有协议排除拦得住。
  2. 域名白名单有三分支(协议相对 / 绝对 / 整页改写各一份),只拆一处另两处还在挡。拆成 M5a/M5b/M5c 分别验证,并补了 //other-site.com/a.jpg 这条只走协议相对分支的用例。
  3. 后台探针在集合为空时会崩(max() 空集合抛 ValueError),崩了没有 FAIL 行,反向验证会把它误判成"注入被抓住了"。加了 crashed() 前置判定 + 空集时只报一条红。

交付

  • 提交 40e09b6(信息带 #3),已推 main
  • 包 kratos_yang-3.2.34.zip 4133853 B,md5 ba4155dfaf29c37f958d26888ffc3c37
  • 公网核验:zip/readme 均 200,下载 md5 与磁盘一致,包内 theme-cdn.php 727 行,readme 顶部是 V3.2.34,历史 24 条版本标题全保留
  • 只发 theme-update/ 三个文件,未解包覆盖服务器主题目录(3.2.24 起的约定),升级请在 WP 后台自行点更新
## 3.2.34 已发布 版本已发到 `theme-update/`,后台「主题设置」里能看到「CDN 加速」标签页(在「邮件通知」之后、「自定义代码」之前)。 ### 落地形态 按需求只做了三样,**没有加启用开关**: | 项 | 类型 | 说明 | |---|---|---| | CDN 地址 | 单行文本,带 placeholder | **留空 = 整个功能关闭**,前台零变化 | | 白名单 | 等宽多行框(10 行) | 命中才加速;**留空 = 全部静态文件都加速** | | 黑名单 | 等宽多行框(10 行) | 命中就不加速;**优先级高于白名单** | 之所以不另加「启用」勾选框:那会多出一种半配置状态(勾了启用、地址忘填),看着是开着的、实际毫无效果。把「填了才生效」写进逻辑,省掉一次误判。 ### 规则写法(一行一条,按字面形态自动识别,不用记语法) ``` * 全部静态文件 jpg / .jpg / *.jpg 按扩展名 jpg,png,webp 一串扩展名,命中任一 /wp-content/uploads/ 以这个路径开头 */uploads/* 通配符,* 可跨斜杠 uploads 路径里含这几个字 ~\/20\d\d\/\d\d\/~ 正则,对完整地址匹配 # 或 ; 开头 注释 ``` ### 有一个歧义必须专门解决 `jpg` 和 `uploads` 在字面上都是「一串纯字母」,分不出谁是扩展名、谁是路径片段。若一律当扩展名,`uploads` 这条会**完全失效,而且没有任何提示** —— 用户只会看到"规则没反应",最难查。 处理办法:单个词**同时按两种含义匹配**(`jpg` 按扩展名命中 .jpg 文件;`uploads` 按路径子串命中 /wp-content/uploads/ 下的文件)。两个含义天然互斥,同时挂上不产生歧义。多个词(`jpg,png`)只按扩展名列表处理。 ### 硬性排除(两套名单都改不了,因为改坏的方式极其致命) - 以斜杠结尾的地址(页面/栏目页/导航)→ 改了访客点导航跳到 CDN 域名,**全站 404** - 页面与动态后缀:php / html / htm / asp / jsp 等 - 没有后缀的地址(接口、短链、伪静态页) - 后台与接口路径:wp-admin、wp-login.php、wp-json、wp-cron.php、xmlrpc.php、/feed/ - 非本站域名(外链、别人家的 CDN) - 非 http(s) 协议:data: / mailto: / tel: / javascript: 后台、REST、AJAX、feed、WP-Cron、定制器预览、命令行**一律不改写**(后台改了会导致编辑器里看不到真实图片,REST 返回的地址与库对不上)。 `?ver=` 这类查询串原样保留 —— 丢了浏览器会一直吃 CDN 上的旧缓存,改了样式前台看不见,是这类功能最常见的事故。 站点装在子目录(`example.com/blog/...`)时,**判规则用完整路径、拼 CDN 时剥掉子目录**,所以规则照原路径写就行,不用为子目录改一遍。 ### 验证 | 探针 | 结果 | |---|---| | 逻辑探针(十组判据:前置/地址写法/七种白名单/黑名单优先/硬性排除/域名/幂等/整页/子目录/正则卫生) | **92 / 0** | | 逻辑反向验证(M1~M15 逐条注入 + E1~E3 等价重写) | **21 / 0** | | 后台探针(真实渲染 + 几何 + 类型 + 说明块,宽窄屏) | **56 / 0** | | 后台反向验证(A1~A12 注入 + E1~E2 等价重写) | **15 / 0** | | 包契约(版本/函数/顺序/三控件/三说明/安全底线/缓冲/源码卫生) | **69 / 0** | | 包契约反向验证(改 zip 内字节,不改源码) | **23 / 0** | | 旧探针回归 | toc330 101/0 · admin330 88/0 · admin328 13/0 · pkgcheck331/332/333 全绿 · e2e322/323 通过 | 反向验证过程中抓出三处**真实盲点**(不是产品 bug,是我的判据不够): 1. **`data:` 协议排除**:原用例 `data:image/png;base64,...` 经 parse_url 后没有扩展名,被「无扩展名」那条顺带挡住了 ⇒ 拆掉协议排除也仍绿。补了一条**带扩展名**的 `data:image/png;base64.a.jpg`,只有协议排除拦得住。 2. **域名白名单有三分支**(协议相对 / 绝对 / 整页改写各一份),只拆一处另两处还在挡。拆成 M5a/M5b/M5c 分别验证,并补了 `//other-site.com/a.jpg` 这条只走协议相对分支的用例。 3. **后台探针在集合为空时会崩**(`max()` 空集合抛 ValueError),崩了没有 FAIL 行,反向验证会把它误判成"注入被抓住了"。加了 `crashed()` 前置判定 + 空集时只报一条红。 ### 交付 - 提交 `40e09b6`(信息带 #3),已推 main - 包 `kratos_yang-3.2.34.zip` 4133853 B,md5 `ba4155dfaf29c37f958d26888ffc3c37` - 公网核验:zip/readme 均 200,下载 md5 与磁盘一致,包内 `theme-cdn.php` 727 行,readme 顶部是 V3.2.34,历史 24 条版本标题全保留 - 只发 `theme-update/` 三个文件,**未解包覆盖服务器主题目录**(3.2.24 起的约定),升级请在 WP 后台自行点更新
Author
Owner

3.2.34 已上线并稳定运行(线上 3.2.34 前台正常,58 个静态资源走 CDN)。用户确认可以关单。

后续在 #4 里追加了「启用开关 + 预制名单」,随 v3.2.35 一起发布。

3.2.34 已上线并稳定运行(线上 3.2.34 前台正常,58 个静态资源走 CDN)。用户确认可以关单。 后续在 #4 里追加了「启用开关 + 预制名单」,随 v3.2.35 一起发布。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/wordpress-kratos-yang#3