qinghuan
← 回到知识探索

后端现场 / 可下载小项目

做一个只在本机运行的 HTTP 缓存实验

保存一段文字的版本标签,再观察服务器什么时候发回正文、什么时候只说内容没变。

展开本文目录
  1. 下载完整练习包
  2. 先让项目在自己的电脑上通过检查
  3. 从第一次拿到文字开始
  4. 带着旧标签再问一次
  5. 只改一个条件,观察旧标签失效
  6. 把观察与实验的边界一起记下来
  7. 记住这三点
  8. 别把例子用过头
  9. 自己试一小步
  10. 查原始资料
  11. 找一份资料继续练
开始前,会这些就够了
  • Node.js 20 或更高版本
  • 会在 PowerShell 中打开文件夹并运行命令
遇到不熟悉的词,先看这 2 个解释
HTTP 请求与响应
客户端用请求说明想访问什么、做什么;服务端用响应说明处理结果,并按需要带回内容。一次网页操作可能触发多组这样的消息交换。
HTTP 状态码
响应里的三位数字,用来说明这次请求处理到了哪种结果,例如成功、需要重定向或发生错误;程序会结合响应内容决定下一步怎样处理。
打开完整术语小抄 ↗

刷新页面后,网络面板里有时会出现状态码 304,看起来像服务器没有返回内容。它并不表示文字被删了,而是在合适的条件下告诉客户端:你保存的那份还可以继续使用。要看清这件事,可以自己控制文字和请求,避免一开始就被浏览器的自动行为打断思路。

这个配套项目只有服务器、验证脚本、中文说明和一次验证记录。它不需要安装额外依赖,也不连接外部服务。你会先预测一次请求的结果,再亲手改变一段教学文字,最后用旧标签和新标签分别询问服务器。

把例子带到自己的电脑上

下载完整练习包

需要 Node.js 20 或更新版本。使用标准库,不需要安装第三方包。下载 ZIP 后选择“全部提取”,进入能看到 README.md 的文件夹。

下载 ZIP · 4 个文件
包里有什么
  • server.cjs:本机教学服务器
  • verify.cjs:自动验证
  • README.md:中文操作步骤
  • verification-result.json:验证记录

在这个文件夹打开 PowerShell,逐行运行

node --version
node verify.cjs

先运行自动验证。想自己发送请求时,再运行 node server.cjs,按 README 在另一个 PowerShell 窗口操作;结束时回到服务窗口按 Ctrl+C。

找不到命令或文件时,先按 README 检查环境和所在目录。文中标出的阅读时间只估算文章篇幅,安装环境和动手练习可按自己的节奏进行。

先让项目在自己的电脑上通过检查

下载配套文件并解压,在包含server.cjs和verify.cjs的文件夹打开PowerShell。先运行node --version确认版本,再运行node .\verify.cjs。验证脚本会自己选择可用端口、启动独立服务并检查响应,结束时只关闭它创建的进程。此时不必手动启动服务器。

末行显示passed,才表示这一轮检查完成。下载包中的verification-result.json只是制作时的记录,不能代替你电脑上的结果。如果出现FAIL,应先读失败项;不要为了避开端口问题结束其他程序,也不要把还没启动成功当成已经验证了缓存。

从第一次拿到文字开始

接着在第一个窗口运行node .\server.cjs。服务默认使用本机地址和3087端口,窗口中的ready行给出实际端口。再打开第二个PowerShell窗口,按README中的完整步骤创建客户端。那段说明保留标签里的双引号,并关闭旧版PowerShell客户端自动添加的上传预告。

先不带任何旧标签读取/message,记录状态、正文和ETag。ETag可以理解为这份内容的版本标签。本项目按实际发送的字节计算标签,所以改一个空格也算改动。它不是账号凭据;这里只用它比较教学文字,不把它当成身份验证。

带着旧标签再问一次

现在先写下预测:内容未改时,带刚才的标签请求,会不会再次收到整段文字?再执行README中的条件请求。请求头If-None-Match携带已有标签,服务器按支持的规则比较,匹配时发送304,响应中没有正文。客户端若需要显示原文,应使用先前保存的内容。

再比较HEAD请求。它只询问响应头信息,成功返回200时同样没有正文,因此不能只凭正文为空判断缓存命中。还要一起看状态和标签。这里的no-cache要求复用前向服务器验证,不是禁止保存;命令行客户端用于观察响应,没有替你实现完整浏览器缓存。

只改一个条件,观察旧标签失效

通过README给出的PUT步骤,把教学文字改成第二版。然后保留最早的标签,再读同一个地址。比较新旧状态、标签和正文,接着用刚收到的新标签再请求一次。整个过程中只改变文字或请求标签,地址和运行中的服务器保持不变,才能说明结果差别来自哪里。

更新只存放在内存里,重启就恢复第一版。正文必须是合法的UTF-8纯文本,最多两千零四十八个字节,不能全是空白。服务器收完并检查后才替换内容;无效字节、过长或超时的上传会失败,不能把失败响应误认为新文字已经生效。

把观察与实验的边界一起记下来

条件头只支持README列出的有限形式:单个带引号标签、弱标签、有限数量的标签列表或单独星号。完整协议允许的形式更多。其他条件请求与带条件的更新会明确被拒绝;这个短项目的作用是看懂流程,不能直接充当通用缓存服务器。

实验后在服务器窗口按Ctrl+C退出,并关闭客户端。这里没有数据库、登录或多人同时编辑保护,也没有测量网络加速倍数。你得到的是一组能重新执行的观察记录:请求带了什么、响应是什么、正文有没有传输,以及停止服务后哪些数据不会保留。

记住这三点

  • 同时记录状态、ETag和正文长度,不能用“没有正文”单独判断缓存命中。
  • 改变文字后,分别用旧标签与新标签请求,才能看清条件请求的作用。
  • 自动验证只操作它启动的本地进程;手动更新只在本次服务器运行期间有效。

别把例子用过头

  • 304没有正文不等于资源不存在,HEAD 200也没有正文。
  • 本项目的条件头解析器有明确子集,不能推广为完整HTTP实现。
  • 字节限制不同于字数限制;中文、英文和换行占用的字节可能不同。

自己试一小步

如果先改成第二版,再逐字改回第一版,最早保存的标签还会得到什么结果?

  1. 保存第一版正文与标签,先写下往返修改后的状态和正文长度预测。
  2. 按README的更新步骤改成第二版,再恢复完全相同的第一版,包括末尾换行。
  3. 最后加一组只修改空格的操作,逐次记录请求方法、标签、状态与正文长度。

做到这些,就算完成

  • 预测与实际记录分开,能定位到具体哪一次请求。
  • 能解释屏幕看起来相近与字节完全相同的区别。
  • 实验完成后退出服务,再确认哪些变化只存在于先前的内存中。

查原始资料

想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。

找一份资料继续练

先选一项,按下面的范围继续学;不必从头读完整门课程。