news 2026/9/21 18:36:49

FreshRSS 0.1—0.7 早期版本演进史:从首个原型到多用户新闻聚合器的技术复盘

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FreshRSS 0.1—0.7 早期版本演进史:从首个原型到多用户新闻聚合器的技术复盘

FreshRSS 0.1—0.7 早期版本演进史:从首个原型到多用户新闻聚合器的技术复盘

【免费下载链接】FreshRSSA free, self-hostable news aggregator…项目地址: https://gitcode.com/gh_mirrors/fr/FreshRSS

导读:本文以仓库内 docs/CHANGELOG-old.md(记录 2013 年 0.1.0 至 2014 年 0.7.1 的法国原版更新日志)为线索,系统复盘 FreshRSS 早期版本的架构演进:从单用户原型到多用户体系、SQL 重构与检索语法、HTML5 内容净化、cookie 与缓存策略,以及至今仍可追溯的代码遗迹。读完本文,你将理解这些"历史版本"如何塑造了今天仓库中的目录结构与核心模块,并掌握intitle:/inurl:/author:等检索关键字、no-cache.txt调试开关等早期设计在当代源码中的真实落点。


一、版本脉络:FreshRSS 早期发布的四个关键阶段

根据 docs/CHANGELOG-old.md,FreshRSS 从 2013 年 4 月 8 日的 0.1.0(标注为"Première version",即首个版本)到 2014 年 2 月 19 日的 0.7.1,共经历约 8 个里程碑发布,可归纳为四个阶段:

阶段版本时间核心主题
原型期0.1.0 ~ 0.2.02013-04 ~ 2013-05首个可运行版本、安装程序、Ajax 刷新
功能成型期0.3.0 ~ 0.4.02013-05 ~ 2013-07i18n、多主题、lazyload、日志页、阅读/全局视图
稳定化期0.5.0 ~ 0.6.12013-10 ~ 2013-11匿名访问控制、token 访问、keep_history、性能修复
架构重构期0.7 ~ 0.7.12014-01 ~ 2014-02多用户模式、SQL 重构、新搜索、HTML5 净化、目录重组

其中 0.7 与 0.7.1 两个版本贡献了日志约 40% 的条目,是早期发展中最重要的一次架构升级,也是下文分析的重点。


二、v0.7 多用户架构:FreshRSS 从"个人工具"走向"自托管平台"

2.1 三种认证方式的引入

v0.7 的核心变化是引入多用户模式:默认用户(管理员)可以创建和删除其他用户。同时,登录方式从单一方案扩展为三种:

  • 表单登录(Form Auth):用户名 + 密码,密码不以明文传输,"相对安全即使没有 HTTPS";要求 JavaScript 与 PHP 5.3+。
  • HTTP 认证:例如在 Apache 下创建./p/i/.htaccess.htpasswd,此时 HTTP 用户名必须与 FreshRSS 用户名一致。
  • Mozilla Persona:通过填写用户的电子邮件地址完成联邦登录(该服务已随 Persona 关停而退出历史舞台)。

该设计在当代源码中仍有明确继承。仓库中 app/Models/Auth.php 依然是认证的核心门面,而 app/Models/FormAuth.php 正是当年"表单登录"路线的直接后代;控制器 app/Controllers/authController.php 负责登录、注册、登出等动作的编排。

2.2 会话 Cookie 策略:目录隔离 + HttpOnly

多用户与匿名可读并存后,v0.7 重写了会话 cookie 策略:

  • cookie 名称采用中性的FreshRSS(避免被部分过滤器误伤);
  • cookie 作用域被限制在./FreshRSS/p/i/目录下,从而让图片、CSS、脚本等静态资源"无 cookie 传输",提升 HTTP 性能;
  • 启用HttpOnly标志增强安全性。

当代实现中,lib/Minz/Session.php 第 51 行显式设置了$params['httponly'] = true;,并支持通过session_name()配置会话名称,正是这条策略的延续。同时,lib/http-conditional.php 在条件请求指纹中混入session_name() . '=' . session_id(),说明会话上下文仍深度参与 HTTP 缓存判定——这是"按用户区分缓存"的关键实现细节。

2.3 目录重组:一切用户数据归入 ./data/

0.7 对文件布局做了大规模整理,核心原则是"所有用户文件统一放入./data/"。日志中列出的关键迁移包括:

  • ./app/configuration/application.ini./data/config.php
  • ./public/data/Configuration.array.php./data/*_user.php
  • ./public/./p/,其中./public/index.php./p/i/index.php(与 cookie 目录策略配套)
  • ./actualize_script.php./app/actualize_script.php(并要求用户同步更新 Cron 配置)

从当前仓库看,这套布局至今基本未变:p/目录存放 Web 入口(p/i/index.phpp/api/等),app/actualize_script.php仍是 CLI 实际化脚本,而data/依然承载users/favicons/PubSubHubbub/等运行时数据。0.6 升级到 0.7 时,只需把旧的application.iniConfiguration.array.php放入新目录./data/;之后各版本升级只需保留./data/目录,安装程序即可完成迁移。


三、SQL 重构与搜索系统:v0.7 的"内功"升级

3.1 表前缀与多用户隔离

v0.7 对数据库做了不兼容重构:所有表以用户名作为前缀,以支持多用户模式;同时压缩在 MySQL 侧完成而非 PHP 侧,显著提升性能并"容忍更大的文章数量"。日志明确提示该版本与 0.6 不兼容,需通过安装程序完成升级。

从源码看,这条路线延续至今:数据库 DAO 均按用户上下文操作,例如 app/Models/FeedDAO.php 的 SQL 均拼接用户级前缀表名;app/Models/CategoryDAO.php 第 38 行的注释直接描述_feed表结构为priority:int, pathEntries:string, httpAuth:string, error:int, keep_history:?int, ttl:int, attributes:string,其中keep_history正是 v0.5.0 新增的字段(见下文)。

3.2 搜索关键字:intitle / inurl / author

v0.7 引入"新搜索引擎"并支持intitle:inurl:author:三类关键字,且可从移动视图访问。这一语法在现代 FreshRSS 中不仅完整保留,还被大幅扩展:

  • app/Models/Search.php 定义了intitleintitle_regexinurlinurl_regexauthorauthor_regextagstags_regex等字段,并支持-intitle:-inurl:等否定形式(见第 426 行附近的序列化逻辑);
  • app/Controllers/searchController.php 第 85、95 行分别用intitle:inurl:构造OR子句,证明这两个关键字在 URL 参数解析层仍然生效;
  • 布尔搜索的完整语法解析位于 app/Models/BooleanSearch.php,承担AND/OR/NOT与括号组合的解析工作。

值得注意的另一点:v0.7 起文章排序以"加入 FreshRSS 的时间"而非"声明日期(常不准确)"为准,这使"全部标记为已读"不会误伤阅读期间新到达的文章,也使得分页变得高效。这一"以入库时间为准"的排序策略是新闻聚合器正确性的关键设计。

3.3 其他 SQL 改进

  • 显示数据库体积(在 FreshRSS 界面内);
  • 修复"将所有收藏标记为已读"的缺陷;
  • 表结构按用户前缀重构后,改善了性能并支持远多于 0.6 的文章数量。

四、HTML5 内容净化与媒体处理

RSS 全文抓取面临的最大风险是外部内容注入,v0.7 在 HTML5 层面做了系统性的安全加固:

  • 原生 HTML5 媒体支持audiovideo及关联元素,默认preload="none",并正确重写资源地址(含 HTTPS 场景);
  • iframe 防护sandbox="allow-scripts allow-same-origin"
  • object/embed 过滤:直接剔除这两类风险标签;
  • 延迟加载:iframe 与 video 使用postpone=""延迟加载,iframe 内的 JavaScript 同样被推迟。

这套净化思路至今仍体现在内容渲染管线中:文章内容在入库与展示前会经过过滤与属性重写处理,且 HTTPS 重写与延迟加载策略与日志描述一致。对自托管阅读器而言,"抓取不可信源 + 安全渲染"是核心工程命题,v0.7 的做法奠定了后续版本的基调。


五、缓存、条件请求与刷新性能(v0.7.1)

0.7.1 的更新重点在于刷新性能与缓存利用:

  • 更快的刷新:充分利用缓存;对不支持条件请求的源,采用"感兴趣内容 MD5 签名"判定是否变化;
  • 刷新队列 JSON 化:待刷新 feed 队列的管理更稳健;
  • 只刷新近期未刷新的 feed,并允许匿名用户触发刷新;
  • SimplePie 升级:修复内存泄漏,增强对无效 feed 的容错。

值得注意的是,条件请求(HTTP Conditional)与缓存键的设计一直延续到今天:lib/http-conditional.php 把会话 ID 纳入缓存指纹,使匿名与登录用户可安全共享 HTTP 缓存。这解释了为何 0.7 会把 cookie 作用域压缩到p/i/——静态资源不带 cookie,才能最大化缓存命中率。

另外,v0.7 引入了开发调试开关:创建./data/no-cache.txt即可禁用 HTTP 缓存。该开关至今有效:app/Controllers/extensionController.php 第 364 行仍检测DATA_PATH . '/no-cache.txt'是否存在,以决定是否跳过条件请求缓存(此处配合httpConditional()使用,缓存时长 604800 秒)。


六、交互与 UI:快捷键、阅读状态与移动端

6.1 快捷键体系(0.7.1)

  • s在只有一种分享方式时直接分享;
  • 多种分享方式依次由123… 激活;
  • Home跳到第一篇,End跳到最后一篇;
  • 新增在分类/feed 间移动的快捷键(配合ShiftAlt修饰键);
  • 快捷键说明按组展示。

当前仓库中快捷键体系已高度可配置化,用户可在配置页自行绑定,视图模板 app/views/configure/shortcut.phtml 承载了快捷键配置界面,底层由FreshRSS_UserConfiguration持久化。

6.2 阅读状态与自动标记

  • 新增"收到即标记已读"选项;
  • "全部标记为已读"后可跳过到下一个含未读的分类/feed(0.5.0 起);
  • 滚轮滚动时自动标记已读(0.4.0 引入,取代"页面加载时标记"的旧选项);
  • 修复阅读导航在末尾处循环的问题,修复点击外部链接图标时误展开文章的问题;
  • 新增收藏筛选与已读筛选视图(0.7);
  • 允许删除某个 feed 的全部文章(0.7)。

这些交互能力在当代代码中仍可对应:阅读模式(normal/global/reader)由 app/Models/ViewMode.php 与 app/Models/ReadingMode.php 管理,视图模板位于 app/views/index/(normal.phtmlglobal.phtmlreader.phtml)。

6.3 移动端与可访问性

0.7 强调"更完善的无障碍":无图片(Unicode 替代)与无 CSS 环境下也能使用;0.4 起移动端拥有更大的按钮与导航栏。0.7 同时改进了窄屏长标题的展示,并支持深色主题(0.7 起新增默认深色主题,主题加载机制更稳健)。


七、分享、导入导出与 OPML

  • 分享目标扩展:0.2 支持邮件与 Shaarli;0.5 增加 Facebook、Twitter、Google+;0.7 扩展 Shaarli、Poche、Diaspora*、Facebook、Twitter、Google+、邮件,并默认绑定s快捷键。
  • OPML:0.7 实现"即时且更宽容"的 OPML 导入,可导入无分类的 feed;0.4 起导入无效 OPML 会显示错误提示。导入后自动触发 feed 刷新(0.6)。
  • 导出:0.2 起支持按 feed 导出 RSS;0.5 起支持为匿名访问生成 token(用于访问 FreshRSS 生成的 RSS 输出)。

在当代仓库中,OPML 导入导出已演进为完整的导入导出服务:app/Services/ImportService.php 与 app/Services/ExportService.php,对应控制器 app/Controllers/importExportController.php,并支持 zip / OPML / SQLite 等多种载体。


八、keep_history:文章保留策略的源头

0.5.0 在feed表新增keep_history字段,用于控制每个 feed 的历史保留策略;0.7 进一步允许"更精细地配置每个 feed 最少保留的文章数"。

从当前源码看,该字段至今仍在活跃使用:

  • app/SQL/install.sql.mysql.php 第 39 行附近可看到INDEX (priority) -- v0.7等带版本注释的建表痕迹;
  • app/Models/CategoryDAO.php 第 47、50 行在整理/清理分类时读取$feed['keep_history'],并在第 77 行执行ALTER TABLE _feed DROP COLUMN keep_history的迁移逻辑;
  • app/Models/Context.php 第 140 行使用keep_history_default计算每 feed 的最小保留数$keepMin
  • app/Models/UserConfiguration.php 声明了keep_history_default属性(旧版 < 1.15 的兼容处理见 app/Controllers/configureController.php 第 376 行)。

也就是说,"每 feed 保留策略"自 0.5.0 提出、0.7 精细化以来,一直是 FreshRSS 架构的稳定组成部分。


九、早期版本留下的工程遗产清单

将日志与当前仓库对照,可梳理出如下"至今可验证"的遗产:

0.1–0.7 引入的特性当代源码落点
表单认证路线app/Models/FormAuth.php、app/Controllers/authController.php
intitle:/inurl:/author:搜索app/Models/Search.php、app/Controllers/searchController.php
keep_history 保留策略app/Models/CategoryDAO.php、app/Models/Context.php
./data/no-cache.txt调试开关app/Controllers/extensionController.php
HttpOnly + 目录限定 cookielib/Minz/Session.php
会话参与条件请求指纹lib/http-conditional.php
./p/./app/actualize_script.php./data/布局仓库根目录即当前布局
快捷键与阅读/全局视图app/views/configure/shortcut.phtml、app/views/index/
导入导出服务app/Services/ImportService.php、app/Services/ExportService.php

十、给运维者与开发者的三条实用结论

  1. 升级历史路径清晰:0.6 及以前版本升级到 0.7 需要迁移配置文件(application.iniConfiguration.array.php./data/),0.7 之后只需保留./data/目录交给安装程序处理。若你维护的是当年遗留实例,这条迁移逻辑是理解数据目录结构的关键。
  2. 缓存与 Cookie 是配套设计:cookie 限定在p/i/+ 静态资源无 cookie + 条件请求指纹混入会话,三者共同支撑了匿名/登录共存下的缓存效率。现代部署若要调优缓存,应同时审视这三处。
  3. 调试手段可复用:开发或排障时,创建data/no-cache.txt可绕过 HTTP 条件缓存;而intitle:inurl:author:关键字在 app/Models/Search.php 中已扩展出正则与否定形式,可作为高级检索入口。

延伸阅读:更新版本(0.8 及以后)的英文更新日志见 docs/CHANGELOG-old2.md,当前主分支的完整变更记录见 CHANGELOG.md。本文所有源码引用均来自当前仓库,行号与文件路径可直接在仓库中定位验证。

【免费下载链接】FreshRSSA free, self-hostable news aggregator…项目地址: https://gitcode.com/gh_mirrors/fr/FreshRSS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 18:36:20

Node.js多版本管理工具Fnm使用指南

1. 为什么需要Node.js版本管理工具作为一名长期使用Node.js的前端开发者&#xff0c;我深刻体会到多版本管理的重要性。在实际开发中&#xff0c;不同项目可能依赖不同版本的Node.js运行环境。比如老项目可能还在用Node.js 12.x&#xff0c;而新项目已经用上了18.x的LTS版本。如…

作者头像 李华
网站建设 2026/9/21 18:36:05

2026最新:3个坑让你欧倍青掉头发更多了,资深老手避坑指南

2026最新:3个坑让你欧倍青掉头发更多了,资深老手避坑指南 翻遍官方文档还是云里雾里?别急,那是你没抓到重点。 很多刚入行的兄弟,面对 欧倍青掉头发更多了 这种典型的技术痛点,第一反应是去啃那几万行的官方源码仓库。 结果呢?头发没救回来,Bug倒是多了三个。 2026最新…

作者头像 李华
网站建设 2026/9/21 18:35:57

XDA助手避坑指南:3步搞懂原理,应届生项目落地不踩雷

XDA助手避坑指南:3步搞懂原理,应届生项目落地不踩雷 刚拿到Offer的应届生,是不是常有一种“书到用时方恨少”的无力感?你背熟了Java集合,Python的装饰器也能信手拈来,但真到了公司里,面对一个需要对接第三方SDK、或者处理底层硬件交互的项目,瞬间就懵了。 这就是典型的…

作者头像 李华
网站建设 2026/9/21 18:35:34

啵乐腐味满满官方网站网址入口源码解析避坑指南

啵乐腐味满满官方网站网址入口源码解析避坑指南 官方文档翻了三遍还是晕?别急,咱们直接看啵乐腐味满满官方网站网址入口背后的源码解析,3秒抓核心。 很多开发者在对接“啵乐腐味满满”这类业务系统时,最头疼的不是功能实现,而是文档。那厚厚几十页的 PDF…

作者头像 李华
网站建设 2026/9/21 18:35:33

央视新址面试坑:3个源码解析误区,别再背八股文了

央视新址面试坑:3个源码解析误区,别再背八股文了 报错日志像天书,StackTrace 滚半天找不到根源?别慌,这其实是 央视新址 项目里最典型的“表象迷惑”。很多开发者盯着日志看,却忽略了底层逻辑,导致排查效率极低。今天这篇 源码解析…

作者头像 李华
网站建设 2026/9/21 18:35:28

3dmax8.0英文版图解原理:前端人3分钟看懂建筑建模核心

3dmax8.0英文版图解原理:前端人3分钟看懂建筑建模核心 官方文档厚得像砖头,翻到第三页就头晕,完全抓不住重点。别急,咱们换个思路,用 图解原理 的方式,把3ds Max 8.0英文版的核心逻辑拆解清楚。 我是做前端的,最近接了个建筑可视化项目,被迫啃了半个月3ds…

作者头像 李华