← 返回题目列表

Content-Type 和 Accept 有什么区别?HTTP 内容协商是怎么做的?

高频 中等 第 6 / 32 题 更新于 2026/07/31
HTTPHeaderContent-TypeAccept内容协商

简化版

Content-Type 表示当前请求体或响应体实际是什么格式,Accept 表示客户端希望接收什么格式。内容协商就是客户端用 AcceptAccept-LanguageAccept-Encoding 等头表达偏好,服务端选择合适表示返回。

详细版

两者最容易混:

  1. Content-Type:描述“我正在发送的 body 是什么”,例如 application/jsonapplication/x-www-form-urlencodedmultipart/form-data
  2. Accept:描述“我希望你返回什么”,例如 application/jsontext/html
  3. 请求里可以同时有两者:POST JSON 请求希望返回 JSON,就会有 Content-Type: application/jsonAccept: application/json
  4. Accept-Encoding 用于压缩协商,如 gzip、br。
  5. Accept-Language 用于语言偏好,如 zh-CNen-US

如果请求体格式和 Content-Type 不匹配,服务端可能解析失败;如果服务端无法满足 Accept,可以返回 406。

完整版教学

一、先分清“发什么”和“想要什么”

Content-TypeAccept 都是 HTTP 头,但方向完全不同。Content-Type 描述当前消息体实际格式,Accept 描述客户端可接受的响应格式。

POST /api/users
Content-Type: application/json
Accept: application/json

{"name":"Tom"}

这里 Content-Type 告诉服务端按 JSON 解析请求体;Accept 告诉服务端最好也返回 JSON。二者不是互斥关系,而是经常一起出现。

记忆钩子:Content-Type 是“我给你的是什么”,Accept 是“我想从你那拿什么”。

二、Content-Type 错了会怎样

服务端通常根据 Content-Type 选择解析器。你明明发 JSON,却写成表单格式,后端就可能从表单解析器里拿不到字段。

请求体正确 Content-Type常见用途
{"a":1}application/jsonAPI JSON
a=1&b=2application/x-www-form-urlencoded普通表单
文件 + 字段multipart/form-data; boundary=...文件上传
XMLapplication/xml老系统集成

举例:后端只接收 application/json,客户端发了 JSON 字符串但头是 text/plain,框架可能不会自动反序列化,最终报 415 或参数为空。

三、Accept 如何表达优先级

Accept 可以带 q 值表示偏好。q 值范围通常是 0~1,越大优先级越高。如果不写,默认权重可理解为 1。

Accept: application/json;q=1.0, text/html;q=0.8, */*;q=0.1

这表示客户端最想要 JSON,也能接受 HTML,实在不行接受任意格式。服务端会结合自己能生成的类型选择一个返回,并在响应里写 Content-Type

四、压缩和语言也是内容协商

内容协商不只 MIME 类型。压缩、语言、字符集也可以协商。现代 Web 常见的是压缩和语言。

Accept-Encoding: br, gzip
Accept-Language: zh-CN, zh;q=0.9, en;q=0.5

Response:
Content-Encoding: br
Content-Language: zh-CN

压缩协商能显著减少传输体积。比如 100KB 的 JSON 经 gzip 可能变成 15KB~30KB,但服务端要付出 CPU 压缩成本,CDN 通常会缓存压缩后的版本。

五、Vary 头为什么重要

如果同一个 URL 会因为 Accept-EncodingAccept-Language 返回不同内容,缓存系统必须知道“这个响应和哪些请求头有关”。Vary 就是告诉缓存 key 要纳入哪些头。

Vary: Accept-Encoding, Accept-Language

没有正确的 Vary,缓存可能把英文页面返回给中文用户,或把 gzip 内容返回给不支持 gzip 的客户端。内容协商和缓存是强相关的。

六、常见错误码怎么理解

内容协商失败时,常见两个状态码:415 Unsupported Media Type406 Not Acceptable。前者偏请求体格式问题,后者偏响应格式无法满足。

状态码谁的问题例子
415客户端发来的 body 格式不支持服务端只收 JSON,客户端发 XML
406服务端无法返回客户端可接受格式客户端只接受 XML,服务端只能 JSON
400body 格式声明对,但内容语法错JSON 少了右括号

面试中把 415 和 406 区分开,是很加分的 HTTP 细节。

七、常见误区与追问

  • 误区:Content-Type 和 Accept 都表示返回格式。 Content-Type 描述当前消息体,Accept 描述客户端期望的响应类型。
  • 误区:GET 请求永远不需要 Content-Type。 GET 通常没有 body,所以少见;但响应仍然必须有 Content-Type。
  • 误区:Accept-Encoding 和 Content-Encoding 是一回事。 前者是客户端可接受的压缩算法,后者是响应实际使用的编码。
  • 追问:为什么上传文件要 multipart/form-data? 它能用 boundary 分隔多个字段和文件内容,适合混合表单。
  • 追问:Vary 有什么用? 告诉缓存系统响应会随哪些请求头变化,避免缓存串内容。
  • 追问:415 和 406 怎么区分? 415 是请求体媒体类型不支持,406 是响应无法满足 Accept。

八、加强记忆

HTTP 内容协商抓住三组对应关系:Content-Type 对“实际 body 类型”,Accept 对“期望响应类型”,Content-Encoding 对“实际压缩方式”。再补上 Vary 影响缓存,就能把 API 调试、文件上传、国际化和压缩都串起来。