blog:miniflux脚本异常

Miniflux 后台无法删除 API Key 的一次排查记录:Cloudflare Rocket Loader 与 CSP 冲突

最近在自建 Miniflux 时遇到一个比较隐蔽的问题:API Key 本身已经可以正常使用,但在 Miniflux 后台页面中点击 API Key 后面的“移除”按钮时,始终无法删除。

这个问题一开始看起来像是 Miniflux 的 API、反向代理、Cookie、BASE_URL 或权限问题,但最后发现真正原因是:

  • Cloudflare 开启了 Rocket Loader;
  • Rocket Loader 向 Miniflux 页面注入了脚本;
  • Miniflux 的 Content Security Policy 阻止了该脚本;
  • 页面 JavaScript 行为异常,导致删除按钮无法正常发起请求。

环境大致如下:

  • Miniflux 使用 Docker 部署;使用端口8043
  • 通过反向代理暴露到域名;
  • 域名经过 Cloudflare;
  • Miniflux 后台地址类似:https://miniflux.example.com/

一开始测试 API Key 时返回:

{"error_message":"access unauthorized"}

后来确认 API Key 问题已经解决,使用如下方式可以正常访问 API:

curl -i \
  -H "X-Auth-Token: 你的API_KEY" \
  http://127.0.0.1:8043/v1/me

但是在 Miniflux 后台的 API Keys 页面,点击“移除”按钮仍然没有反应。

首先检查 Miniflux 服务是否正常:

curl -i http://127.0.0.1:8043/healthcheck

返回:

HTTP/1.1 200 OK

OK

说明服务本身正常。

继续测试 API 路径:

curl -i http://127.0.0.1:8043/v1/me

返回:

HTTP/1.1 401 Unauthorized

{"error_message":"access unauthorized"}

这里的 401 是正常的,因为没有携带认证信息。它反而说明:

  • /v1/me 路径存在;
  • API 路径没有 404;
  • Miniflux API 服务是可访问的。

再测试错误的子路径:

curl -i http://127.0.0.1:8043/rss/v1/me

返回类似:

HTTP/1.1 302 Found
Location: /?redirect_url=%2Frss%2Fv1%2Fme

这说明 /rss/v1/me 被当作普通网页路径处理,并不是正确的 API 路径。

因此可以判断:本例中 API 正确路径应为:

/v1/me

而不是:

/rss/v1/me

为了确认后端是否真的可以删除 API Key,可以绕过网页,直接使用 API 删除。

先列出 API Keys:

curl -i -u '你的用户名:你的密码' \
  http://127.0.0.1:8043/v1/api-keys

找到要删除的 Key ID 后执行:

curl -i -X DELETE -u '你的用户名:你的密码' \
  http://127.0.0.1:8043/v1/api-keys/要删除的ID

如果返回:

HTTP/1.1 204 No Content

说明 Miniflux 后端删除功能是正常的。

这时问题就不在数据库,也不在 API Key 本身,而更可能在网页前端、浏览器、反向代理或 CDN 层。

接着打开浏览器开发者工具:

  1. 切换到 Network 面板;
  2. 点击 API Key 后面的“移除”按钮;
  3. 观察是否有新的请求发出。

结果发现:

  • 点击按钮后没有任何新的网络请求;
  • 页面 URL 只是从:
https://miniflux.example.com/keys

变成了:

https://miniflux.example.com/keys#

这个现象非常关键。

# 只是页面锚点变化,说明点击的是类似这样的前端链接:

<a href="#">移除</a>

正常情况下,页面 JavaScript 应该拦截这个点击事件,然后发起删除请求。

但现在只出现了 #,没有发请求,说明 JavaScript 没有正常执行。

继续查看浏览器开发者工具里的 Console 面板,发现如下报错:

Refused to load https://miniflux.example.com/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js because it does not appear in the script-src directive of the Content Security Policy.

这个错误说明:

  • Cloudflare 正在向页面注入 Rocket Loader 脚本;
  • Miniflux 页面设置了 Content Security Policy;
  • CSP 不允许加载 Cloudflare 注入的 rocket-loader.min.js
  • 浏览器拒绝加载该脚本;
  • 页面脚本执行受到影响。

最终确认,这就是后台按钮失效的原因。

进入 Cloudflare 后台,关闭 Rocket Loader。

大致路径为:

Cloudflare Dashboard
  -> 选择对应域名
  -> Speed
  -> Optimization
  -> Rocket Loader
  -> Off

如果不想影响整个域名,可以只针对 Miniflux 子域名关闭 Rocket Loader,例如:

Hostname equals miniflux.example.com
Rocket Loader = Off

关闭后建议再执行以下操作:

  1. 清理 Cloudflare 缓存;
  2. 浏览器按 Ctrl + F5 强制刷新;
  3. 或者使用无痕窗口重新登录;
  4. 再次进入 Miniflux 后台 API Keys 页面;
  5. 点击“移除”按钮。

此时删除按钮恢复正常。

这个问题容易被误判为以下几类问题:

因为最开始 API 返回过:

{"error_message":"access unauthorized"}

但这个错误只代表认证失败,不代表后台删除按钮的问题。

正确测试方式是带上 X-Auth-Token

curl -i \
  -H "X-Auth-Token: 你的API_KEY" \
  http://127.0.0.1:8043/v1/me

如果访问 /v1/me 返回 404,确实可能是路径或反代问题。

但本例中:

curl -i http://127.0.0.1:8043/v1/me

返回的是 401,而不是 404。

这说明 API 路径是存在的,只是没有认证。

Miniflux 的 BASE_URL 确实很重要,尤其是经过域名、HTTPS 或子路径访问时。

例如独立子域名部署时:

environment:
  - BASE_URL=https://miniflux.example.com/

如果是子路径部署,例如:

https://example.com/miniflux/

则应配置为:

environment:
  - BASE_URL=https://example.com/miniflux/

但本例中,最终故障点并不是 BASE_URL,而是 Cloudflare Rocket Loader 注入脚本与 CSP 冲突。

后台会话中看到类似:

172.20.0.1

这通常是 Docker 网桥或反向代理容器的 IP,不一定是故障。

如果需要让 Miniflux 识别真实客户端 IP,可以检查反向代理 Header:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

必要时还可以配置 Miniflux 信任反代网络:

environment:
  - TRUSTED_REVERSE_PROXY_NETWORKS=172.20.0.0/16

但这同样不是本次删除按钮失效的根因。

如果你也遇到 Miniflux 后台按钮无反应,可以按这个顺序排查:

curl -i http://127.0.0.1:8043/healthcheck
curl -i http://127.0.0.1:8043/v1/me

如果 /healthcheck 返回 200,/v1/me 返回 401,说明服务和 API 路径基本正常。

使用 Basic Auth 测试:

curl -i -u '你的用户名:你的密码' \
  http://127.0.0.1:8043/v1/me

使用 API Key 测试:

curl -i \
  -H "X-Auth-Token: 你的API_KEY" \
  http://127.0.0.1:8043/v1/me

点击按钮后,如果完全没有请求发出,只是 URL 多了一个 #,说明问题大概率在前端 JavaScript。

如果看到类似:

Refused to load ... rocket-loader.min.js ...
Content Security Policy

就优先检查 Cloudflare Rocket Loader。

关闭后强制刷新页面,再测试后台按钮。

这次问题的核心不是 Miniflux API,也不是 API Key 本身,而是 Cloudflare Rocket Loader 与 Miniflux 页面 CSP 冲突。

最终表现为:

  • API Key 可以正常使用;
  • 后台点击“移除”按钮没有请求发出;
  • URL 只从 /keys 变成 /keys#
  • 控制台出现 Rocket Loader 被 CSP 拒绝加载的错误;
  • 关闭 Cloudflare Rocket Loader 后问题解决。

如果自建服务后台页面出现“按钮点击无反应”“没有请求发出”“URL 只多了 #”这类现象,不要只盯着后端日志,也要第一时间检查浏览器 Console。很多时候,真正的问题发生在前端脚本执行阶段。

请输入您的评论:
请在输入框中填入验证码以证明您不是机器人。
 
  • blog/miniflux脚本异常.txt
  • 最后更改: 2026/05/23 05:46
  • doge24190