内容协商是什么
内容协商是客户端与服务端就「用哪种表述返回」达成一致的过程:客户端通过 Accept、Accept-Language、Accept-Encoding 声明偏好与权重,服务端选择自己支持的一种表述,并在响应头 Content-Type 与 Content-Encoding 中声明实际结果。它让同一资源以不同结构、语言或压缩形式服务不同调用方,而不必为每种格式各开一组接口。
声明不支持时怎么处理
当客户端声明的格式服务端都不支持时,规范做法是返回 406 并在响应中说明服务端支持哪些格式,而不是默默退回默认格式。现实中大量接口固定返回结构体格式并忽略其余偏好,这本身可以接受,但必须写进文档,否则接入方会以为切换格式的声明是生效的,直到解析失败才察觉。协商结果与缓存的关系也要理清:编码与语言不同,缓存必须分开存放。
基本信息
| 请求头 | Accept 声明媒体类型偏好并用 q 值表达权重,Accept-Language 声明语言,Accept-Encoding 声明压缩算法 |
|---|---|
| 响应头 | Content-Type 声明实际媒体类型,Content-Encoding 声明实际压缩编码 |
| 权重规则 | q 值从高到低选择,未声明 q 视为默认优先级 |
| 失败处理 | 所有偏好都不支持时返回 406,并说明服务端支持的格式 |
| 缓存关联 | 不同编码与不同语言的响应必须使用不同缓存键 |
常见请求头
| 请求头 | 作用 | 示例值 |
|---|---|---|
| Accept | 声明可接受的媒体类型 | application/json;q=1.0, application/xml;q=0.5 |
| Accept-Encoding | 声明可接受的压缩算法 | gzip, br |
| Accept-Language | 声明语言偏好 | zh-CN, en;q=0.8 |
| Content-Type | 声明请求体的实际类型 | application/json |
典型使用场景
- 同一份接口同时服务浏览器与第三方系统,需要返回不同格式
- 用媒体类型承载接口版本,避免把版本号塞进路径
- 客户端声明可接受的压缩算法,由服务端或网关按能力压缩响应
- 多语言场景下按语言偏好返回不同文案,而不是靠额外参数
协商偏好要写进接口文档并给出默认规则:固定返回一种格式并忽略其他偏好是常见做法,但写不明白就会让接入方误解。
缓存键不含编码与语言维度时,压缩内容与原文、不同语言版本会互相覆盖,表现为偶发的解析失败,排查难度很高。