描述客户端愿意接收哪些媒体类型的一系列 HTTP 头。

Accept 系列头让服务器协商应答

内容协商是在服务器能够实际生成的表示之间进行选择。请求偏好只是选择的输入,并不能证明响应已经满足这些偏好,客户端仍需检查收到的表示。Vary 记录影响复用的请求维度,不负责命名最后选中的格式、语言或压缩方式。把选择输入与响应结果混为一谈,会让排查从一开始就看错字段。 分开看待不同维度 请求偏好 所选表示的响应元数据 Accept Content-Type Accept-Language Content-Language Accept-Encoding 实际施加内容编码时的 Content-Encoding 这些维度相互独立,请求 JSON 不等于请求英文或 gzip。Content-Language 描述内容所面向受众的语言,不保证每个字符都属于某一种语言。如果服务器只有英文 HTML 和中文 JSON,不能把分别算出的“最优格式”和“最优语言”拼成根本不存在的中文 HTML。应先列清实际可用的完整组合,再定义选择规则;偏好不能凭空增加服务端的生成能力。 质量值范围是零到一,省略时为一,最多允许三位小数。零表示不可接受,不是“稍微不喜欢”。对媒体类型,一个候选的质量值由匹配它的最具体范围决定。显式的 text/html;q=0 不会被更宽泛的 */*;q=1 解禁。如果只是找整串字段里最大的数字,或者拿逗号前第一项,就会丢掉“哪个范围约束哪个候选”的关系,得到看似按权重处理、实际上违反排除条件的结果。 坏掉的样子 缺失某个偏好字段通常表示在该维度上没有偏好,并不等同于显式拒绝。RFC 9110 允许服务器在没有可接受表示时返回 406,也允许忽略该字段,因此默认响应可能仍然无法被客户端使用。承诺严格协商的 API 必须自己明确这项策略。客户端可以表达排除条件,却不能仅靠发出这个字段,强迫所有现网服务器都执行严格拒绝逻辑。 各类字段还存在不同的匹配语义。Accept 使用媒体范围,语言协商需要约定语言标签匹配方式,Accept-Encoding 则有 identity、字段缺失和空值的专门规则。通用列表解析器不会自动补齐所有业务策略。特别是不能把缺失字段悄悄变成一个空集合,再推导出“客户端拒绝一切”。应用选择默认值与解析器返回没有匹配项,是两个需要明确区分的事实。 相同权重也没有一条跨所有服务器通用的顺序规则。应用应让并列时的选择可预测,并实际测试。完整的语言偏好还可能帮助识别用户,因此记录全部偏好档案、把所有可能字段都放进 Vary,并非天然合理。Vary 只处理匹配问题,缓存资格、新鲜度和授权边界仍需各自的规则,不能因为增加了这个字段就认定内容可以共享。 快速验证 准备 Python 3.11 或更新版本及 POSIX shell,在临时环境安装本次验证的解析器,再用 "$accept_lab/venv/bin/python" 运行 Python 代码。安装需要外网,实验本身不发请求、不启动服务器。它验证的是 Werkzeug 3.1.8 的候选选择行为,不是假装复现任意浏览器或 CDN 的完整实现。 ...

十一月 23, 2027 · 2 分钟 · XB Field Notes
一种让同一个 URL 按请求头返回不同表示的协议机制。

Accept 与 Vary 让一个 URL 回应多种格式

同一个资源可以同时提供面向读者的 HTML 视图和面向程序的 JSON 表示。共用 URL 的前提是源站与中间层始终保留这种区别。端点需要选择可用格式、正确序列化、说明缓存变化维度,并验证本次选中的表示,而不是拿同一资源的另一种版本来代替它。单一地址不会自动完成这些工作。 先选择,再序列化与验证 对于 GET 响应,请求中的 Accept 表达希望接收哪些媒体类型,请求中的 Content-Type 则描述请求内容本身。把后者写成 JSON,并不等于要求服务器返回 JSON。质量值与通配符匹配应交给框架已有的媒体范围解析器。应用还需要分别规定:没有 Accept 时默认返回什么,以及字段存在却匹配不到任何可用表示时如何处理。 下面的端点只在 Accept 缺失时默认选择 HTML。如果客户端明确表达的偏好没有可接受候选,就返回 406,并列出可用类型。这是一项刻意选择的接口策略,因为 HTTP 也允许忽略偏好。不要把它换成 415,后者针对的是请求内容格式不受支持。分清错误方向,客户端才能知道应该修改希望接收的类型,还是自己发送的正文及其声明。 完成选择后,Content-Type 应由实际使用的序列化方式确定。HTML 中插入数据需要适当转义,JSON 则应通过 JSON 序列化器生成,而不是塞进 HTML 模板。该路由的各类表示,包括默认表示,都需要 Vary: Accept。但 Vary 不授予存储资格,也不保护个人信息;实验中的公开缓存指令只适用于这份对所有调用者完全相同、没有敏感信息的固定状态记录,不能直接复制到账户接口。 坏掉的样子 只测源站,可能看不出缓存正在把之前的 HTML 发给现在的 JSON 请求。需要通过完整交付路径检查响应头和解析后的正文,并交换请求顺序。新响应补上正确的 Vary,不会自动修复此前已经缓存、却缺失选择元数据的条目。应使用受控测试地址或已获批准的失效流程,不要为了验证一个端点而随意清空共享缓存。 ...

一月 19, 2027 · 2 分钟 · XB Field Notes