尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

specification.website 的 Accept: text/markdown 内容协商:Vary: Accept 与缓存陷阱的前端工程完整解析

specification.website 的 Accept: text/markdown 内容协商:Vary: Accept 与缓存陷阱的前端工程完整解析 specification.website 的 Accept: text/markdown 内容协商Vary: Accept 与缓存陷阱的前端工程完整解析【免费下载链接】specification.websiteWebsite specification — HTML, accessibility, security, SEO, agent-readiness. Platform-agnostic, sourced, MIT.项目地址: https://gitcode.com/gh_mirrors/sp/specification.websitespecification.website 是一个把好网站应该做什么写成规范条款的开源站点覆盖 HTML、可访问性、安全与 SEO并用 Accept: text/markdown 内容协商 Vary: Accept 为 AI 代理提供无损的 Markdown 内容源。本文完整解析它如何在前端工程层面实现 HTTP 内容协商以及为什么少一行Vary头就会让 CDN 缓存踩坑。Accept: text/markdown 是什么同一 URL两种表示形式传统上一个 URL 只有一种表示形式representation。AI 时代的新约定是代理在请求头里声明Accept: text/markdown服务端就把同一页的原始 Markdown 源码含 YAML frontmatter 元数据原样返回而不是渲染后的 HTML。为什么值得这么做无损HTML 解析会丢失标题语义、代码块语言标记和内联元数据Markdown 源码一字不差更小剥离样式、脚本和公共骨架后Markdown 通常只有 HTML 体积的 1/51/20免 JS不跑 JavaScript 的爬虫也能拿到完整内容。specification.website 对三类路径全部启用协商请求路径默认返回带上Accept: text/markdown后/spec/分类/slug/规范页 HTML该页的.md源码/站点根首页 HTML/llms.txt站点索引/checklist/检查清单 HTML/checklist.md任务清单项目自己的规范页 markdown-source-endpoints.md 把这一约定总结为URL 后缀.md是基础内容协商是上一层——内容不变URL 保持规范canonical缓存行为正确。Vary: Accept 缓存陷阱为什么 CDN 可能把 HTML 发给 AI 代理先看这个真实的故障场景项目规范页称之为最经典的Common mistakes# 请求 1浏览器访问缓存命中并存储 GET /spec/security/hsts/ Accept: text/html → 200 OK (Content-Type: text/html) ← 缓存层存下这份 HTML # 请求 2AI 代理访问同一 URL GET /spec/security/hsts/ Accept: text/markdown → 200 OK (Content-Type: text/html) ← 缓存直接吐出第一份 HTML问题出在缓存键。HTTP 缓存默认只以URL作为键Accept不同但 URL 相同。如果响应没有声明我对Accept敏感缓存就会把第一次命中的表示形式返回给之后所有客户端——于是代理收到 HTMLtoken 浪费不说内容结构也全乱了。Vary头就是解药。Vary: Accept告诉缓存层同一个 URL响应内容取决于请求的Accept头请按(URL, Accept)组合建缓存键。 没有这行头内容协商等于没做。关键细节是双向的不仅 Markdown 响应要带Vary: AcceptHTML 响应也必须带——因为 HTML 是先到达缓存的那份恰恰是它需要声明敏感性。这正是 specification.website 中间件注释里写的appended to spec-page HTML responses so caches dont conflate the two representations避免缓存把两种表示形式混为一谈。实现解剖在 Cloudflare Pages 中间件里做协商整个协商逻辑集中在 functions/_middleware.ts部署为 Cloudflare Pages 的边缘中间件edge middleware执行顺序先记日志入口第一句调用 logBot()把疑似爬虫/代理的请求写入 Analytics Engine。注意Accept: text/markdown本身就是代理身份信号——浏览器默认要text/html只有代理会显式要 Markdown判断意图prefersMarkdown()用正则text/markdown精确匹配Accept头刻意不做完整 media-range 解析浏览器不会误触命中规范页正则/^\/spec\/([^/])\/([^/])\/?$/匹配到/spec/分类/slug/后内部回源取/spec/分类/slug.md静态资源改写响应头headers.set(Content-Type, text/markdown; charsetutf-8); headers.set(Vary, Accept, Want-Content-Digest); headers.set(Content-Location, mdPath);三个头各司其职Content-Type: text/markdown——明示协商结果防止浏览器把 Markdown 当附件下载Content-Location——告诉客户端这份内容的规范地址即.mdURL客户端可以据此换直连Vary: Accept, Want-Content-Digest——第二维Vary是因为项目还响应 RFC 9530 的Want-Content-Digest请求头客户端可指定摘要算法偏好值 0–10算法不同则响应字节不同缓存键必须包含它。而.md源码本身由 Astro 在构建期从内容集合生成src/pages/spec/[category]/[slug].md.ts与 HTML 页同源同构建从根上保证两份内容不漂移——这也是规范页列出的另一条常见错误letting the Markdown drift from the HTML。配套的静态策略在 public/_headers 里/spec/*.md、/checklist.md、/okf/*统一给出text/markdown内容类型和Cache-Control: public, max-age3600, stale-if-error86400——缓存 1 小时、源站故障时允许用 1 天内的旧内容兜底。同时 public/_routes.json 把/_astro/*、/fonts/*等静态资产排除在 Workers 路由之外确保日志与协商逻辑只在 HTML 和 well-known 路径上运行不拖慢静态资源。进阶细节完整性摘要、代理识别与 Server-Timing三个容易被忽略、但体现规范即实践的工程点 完整性摘要只对 Markdown 计算。协商出的 Markdown 响应会附带Content-Digest/Repr-DigestRFC 9530让代理可以校验字节未被中间环节篡改或截断。而 HTML 响应刻意不加——因为边缘在中间件返回后还会对 HTML 做 brotli 压缩此时算出的摘要描述的是客户端永远收不到的字节校验必失败。注释里写得很直白This is precisely why the digest is scoped to Markdown and never added to HTML. 用内容类型当身份信号。bot-detect.ts 按四个信号优先级识别代理Web Bot Auth 签名 UA 匹配 Cloudflare 验证 Accept: text/markdown。最后一级意味着哪怕代理伪装了 UA只要它要 Markdown就会被记入AGENT_LOG数据集供/admin/stats面板统计。日志全程try/catch包裹绝不因日志失败而打断请求。⏱️ 每个响应带Server-Timing。中间件为每条响应追加Server-Timing: edge;deschtml|markdown;durms同源可直接读取顺带演示了性能观测规范页的要求。如何验证4 条 curl 自查清单照搬项目规范页的 Verification 小节任何站点都可以这样验收自己的内容协商curl -i 页.md→ 返回200且Content-Type: text/markdown; charsetutf-8curl -i -H Accept: text/markdown 规范URL/→ 返回 Markdown且带Content-Location与Vary: Acceptcurl -I 规范URL/不带 Accept→ HTML 响应同样带Vary: Accept最容易被漏掉的一条对比.md与 HTML 的标题、段落、代码块一致且 Markdown 顶部带 frontmatter。小结specification.website 用不到百行的边缘中间件把三个 HTTP 头——Accept、Content-Location、Vary——组合成一套完整的内容协商方案代理拿到低成本、无损的 Markdown 源码CDN 缓存因Vary: Accept而各得其所HTML 用户毫无感知。它的核心教训只有一句做内容协商永远不要忘记给先到缓存的那份响应也加上Vary。项目里所有细节都能在同一仓库的规范页markdown-source-endpoints.md和中间件源码中找到出处——规范与实践互为镜像这正是这个项目最有参考价值的地方。【免费下载链接】specification.websiteWebsite specification — HTML, accessibility, security, SEO, agent-readiness. Platform-agnostic, sourced, MIT.项目地址: https://gitcode.com/gh_mirrors/sp/specification.website创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表