关于常用的 HTTP 请求头以及响应头详解
Category(分类): NET Protocol Status: 未知
HTTP 报文头用于描述请求或响应的属性。请求头通常由客户端发送,响应头通常由服务器发送,但有些字段(例如 Cache-Control、Connection、Content-Type)既可以出现在请求中,也可以出现在响应中,只是具体含义可能不同。
本文中的示例主要针对 HTTP/1.1。HTTP/2 和 HTTP/3 使用二进制帧和伪首部字段(例如 :method、:scheme、:authority、:path),不应直接照搬 HTTP/1.1 中的 Connection 和 Transfer-Encoding 等连接级字段。
HTTP 头字段名称不区分大小写。示例中的分隔符必须使用半角冒号
:,而不是中文全角冒号:。
一、常用的 HTTP 请求头
1. Accept
Accept 用于告诉服务器,客户端希望接收哪些媒体类型(MIME type)的响应。
Accept: text/html
表示客户端优先接受 text/html 类型的响应。
Accept: */*
表示客户端对响应媒体类型不作限制,即可以接受任意媒体类型。它不代表浏览器的业务代码一定能够处理所有类型;不同浏览器、不同请求场景发送的 Accept 值也可能不同,不能简单认为所有浏览器都会发送 */*。
服务器根据 Accept 选择响应类型时,通常会返回相应的 Content-Type。如果服务器无法提供客户端可接受的类型,可能返回 406 Not Acceptable。
2. Accept-Encoding
Accept-Encoding: gzip, deflate
Accept-Encoding 用于声明客户端支持的内容编码,常见值包括 gzip、br、deflate 和 zstd。它描述的是压缩或其他表示编码方式,不是字符集编码。
服务器选择编码后,会通过响应头 Content-Encoding 告诉客户端实际使用的编码。例如:
Accept-Encoding: gzip, br
Content-Encoding: br
表示客户端声明支持 gzip 和 Brotli,而服务器最终选择使用 Brotli。服务器根据该请求头返回不同内容时,通常还应设置 Vary: Accept-Encoding,避免缓存错误复用不同编码的响应。
3. Accept-Language
Accept-Language: zh-CN, zh;q=0.9
Accept-Language 用于声明客户端偏好的自然语言。q 是权重,范围通常为 0 到 1,数值越大表示优先级越高。
它只是语言偏好,不代表服务器一定能提供对应语言。服务器可能根据该字段选择内容语言,并通过 Content-Language 告知实际使用的语言。
4. Connection
Connection 是 HTTP/1.1 中的连接级(hop-by-hop)字段,用于表达当前连接的处理方式,不能被代理无条件转发给下一跳。
Connection: keep-alive
在 HTTP/1.1 中,持久连接本来就是默认行为,通常不需要显式发送 keep-alive。持久连接只表示连接可以被后续请求复用,并不保证服务器或客户端一定不会主动关闭连接。
Connection: close
表示发送方希望在当前请求对应的响应完成后关闭连接,后续请求不能继续复用这条连接。它并不表示在请求刚发送完成的瞬间就关闭 TCP 连接。
HTTP/2 和 HTTP/3 不使用 Connection: keep-alive 来管理连接,Connection 这类连接级字段也不应出现在 HTTP/2 或 HTTP/3 报文中。
5. Host
Host: www.baidu.com
Host 用于指定请求目标的主机和端口,通常可以从请求 URL 的 authority 部分得到。它对 HTTP/1.1 请求是必需的,服务器可以利用它在同一个 IP 地址上区分不同的虚拟主机。
如果端口是协议的默认端口,通常可以省略:
Host: example.com
Host: example.com:8080
HTTP/2 和 HTTP/3 通常使用 :authority 伪首部表达相同的目标信息;Host 可能作为兼容字段存在,但不能将 HTTP/1.1 的写法直接等同于 HTTP/2/3 的报文格式。
6. Referer
Referer: https://www.baidu.com/?tn=62095104_8_oem_dg
Referer(该拼写是 HTTP 历史遗留的故意拼写)通常用于表示当前请求来源页面的 URL,服务器可以据此进行统计、日志记录、来源判断等处理。
浏览器不一定会发送完整的 Referer。Referrer-Policy、隐私保护、从 HTTPS 页面跳转到 HTTP 页面等情况,都可能导致 Referer 被省略或只发送 origin。它也不是可靠的身份认证信息,不能单独用来判断请求是否合法。
7. User-Agent
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
User-Agent 是客户端对自身软件、操作系统和浏览器环境的描述,服务器可以据此进行兼容性处理、统计或日志记录。
User-Agent 是客户端自行提供的字符串,容易被伪造,不能作为可靠的身份认证依据。现代浏览器还可能通过 User-Agent Reduction 或 User-Agent Client Hints 限制可暴露的信息。
8. Cache-Control(请求缓存控制)
Cache-Control 既可以出现在请求中,也可以出现在响应中。请求和响应支持的指令并不完全相同,不能把响应指令直接当成请求指令使用。
常见的请求指令包括:
Cache-Control: no-cache
要求缓存不要直接使用已有响应,使用前应向服务器重新验证。它不等于“完全不允许缓存”。
Cache-Control: no-store
要求缓存不要存储本次请求或响应的内容。它比 no-cache 更严格,但也不应被理解为能够阻止所有日志、浏览器扩展或其他系统组件留下任何数据。
Cache-Control: max-age=0
表示客户端不接受已经超过 0 秒的新鲜响应,实践中常用于要求缓存重新验证。
Cache-Control: only-if-cached
表示只接受缓存中的响应,不要为了满足本次请求而访问源服务器;如果缓存没有可用响应,可能返回 504 Gateway Timeout。
9. Cookie
Cookie 用于在客户端保存少量状态信息,并在后续符合域名、路径等条件的请求中自动发送给服务器。服务器通常通过响应头 Set-Cookie 创建 Cookie,浏览器随后通过请求头 Cookie 发送它。
Cookie 常用于保存会话标识、短期令牌、用户偏好等信息,例如:
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax
Cookie: sessionId=abc123
不应该在 Cookie 中保存明文密码。Cookie 也不是天然安全的身份凭证,实际使用时应根据场景配置 Secure、HttpOnly、SameSite、过期时间和合适的域名/路径范围。
10. Range(用于部分内容或断点续传)
Range: bytes=0-5
Range 用于请求资源的一部分。0-5 表示从第 0 个字节到第 5 个字节,首尾都包含在范围内,共 6 个字节。
服务器支持并成功处理时,通常返回:
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 0-5/7877
其中 Content-Range 表示本次响应覆盖的范围和完整资源大小。服务器也可能忽略 Range,直接返回完整资源和 200 OK;如果范围无效,可能返回 416 Range Not Satisfiable。
二、常用的 HTTP 响应头
1. Cache-Control(响应缓存控制)
Cache-Control: private
表示响应只能由用户的私有缓存(例如浏览器缓存)存储,不能被共享缓存提供给其他用户。private 不是所有响应的默认值,是否可缓存还要结合响应状态、请求方法、认证信息和其他缓存指令判断。
Cache-Control: public
表示共享缓存也可以存储该响应,即使它在某些默认规则下可能不会被共享缓存保存。但这并不意味着响应一定会被缓存,仍然需要满足新鲜度和其他缓存条件。
Cache-Control: must-revalidate
表示响应变为过期后,缓存不能直接继续使用它,必须先向源服务器重新验证。它不是要求代理服务器对每一次请求都访问服务器。
Cache-Control: no-cache
表示响应可以被缓存,但缓存每次复用前都必须成功重新验证。如果目标是完全禁止缓存,应使用 no-store。
Cache-Control: max-age=10
表示响应在生成后的 10 秒内可以被缓存直接复用,10 秒后通常需要重新验证或重新获取。这里的 max-age 是以秒为单位的相对时间,不是日期。共享缓存还可以使用 s-maxage 指定不同的新鲜时间。
Cache-Control: no-store
要求浏览器缓存和共享缓存都不要存储请求或响应的内容,也不要使用已存储的响应来满足其他请求。它主要约束缓存,并不是对日志、抓包、浏览器扩展或操作系统行为的绝对隐私保证。
当响应同时包含 Cache-Control: max-age 和 Expires 时,现代缓存通常优先使用 max-age。缓存策略还可能受到 Vary、验证器和响应状态码等因素影响。
2. Content-Type
Content-Type: text/html; charset=UTF-8
Content-Type 用于声明报文中表示内容的媒体类型,以及可选的字符集参数。客户端可以根据它决定如何解释响应,例如 text/html 通常会按照 HTML 文档处理,application/json 通常会按照 JSON 数据处理。
charset=UTF-8 表示文本内容使用 UTF-8 字符集。服务器应返回正确的媒体类型和字符集,否则可能出现乱码或被浏览器以不符合预期的方式处理。Content-Type 也可以出现在请求中,用于描述请求体的类型,例如提交 JSON 时使用 application/json。
3. Content-Encoding
Content-Encoding: gzip
Content-Encoding 表示服务器在原始表示内容上使用了 gzip 等内容编码。客户端收到后通常会先解压,再根据 Content-Type 和字符集解析内容。
它与字符集编码不是一回事:字符集由 Content-Type 的 charset 参数等信息描述,压缩方式由 Content-Encoding 描述。
4. Date
Date: Tue, 03 Apr 2018 03:52:28 GMT
Date 表示 HTTP 消息的生成时间,通常由源服务器或中间服务器生成,不一定等同于资源文件的修改时间,也不一定是客户端收到响应时的本地时间。
HTTP 日期使用统一的 HTTP-date 格式,示例中的 GMT 是规范要求的时间表示方式,用于避免不同时区造成歧义。
5. Server
Server: Tengine/1.4.6
Server 用于描述生成响应的服务器软件信息。服务器可以省略、简化或修改该字段,因此它不一定会准确暴露服务器类型和版本。生产环境中通常不建议暴露过多版本信息,以减少指纹识别和攻击面。
6. Transfer-Encoding
Transfer-Encoding: chunked
在 HTTP/1.1 中,Transfer-Encoding: chunked 表示消息体采用分块传输编码进行分帧。每个块前面会带有该块大小,最后使用大小为 0 的块表示消息体结束,末尾还可以携带 trailers。
分块是传输层面的消息分帧,不代表资源被拆成了互相独立的文件,也不代表只有动态资源才能使用。动态生成且事先不知道完整长度的响应经常使用 chunked,但静态资源也可以使用它。
Transfer-Encoding 是 HTTP/1.1 的传输机制,HTTP/2 和 HTTP/3 使用自己的帧结构,不使用 HTTP/1.1 的 chunked 编码。若 HTTP/1.1 响应使用 chunked,通常不再同时发送 Content-Length。
7. Expires
Expires: Sat, 01 Jan 2000 01:00:00 GMT
Expires 是一个与缓存有关的旧式响应头,用绝对时间表示响应何时变为过期。客户端和服务器时钟不一致时可能造成判断偏差,因此现代应用通常优先使用 Cache-Control: max-age=N。
Cache-Control: max-age=600
这里的 600 表示 600 秒,而不是一个日期。当 max-age 存在时,缓存通常优先使用它,而不是 Expires。
8. Last-Modified
Last-Modified: Sat, 26 Dec 2015 17:30:00 GMT
Last-Modified 表示所请求表示的最近修改时间。它可以与请求头 If-Modified-Since 配合进行条件请求:如果资源没有变化,服务器可以返回 304 Not Modified,让客户端继续使用缓存。
它不一定等同于操作系统文件的精确修改时间,而且时间精度和服务器实现可能导致它不如 ETag 精确。实际缓存验证时通常可以同时使用 Last-Modified 和 ETag。
9. Connection
Connection: keep-alive
在 HTTP/1.1 中,持久连接默认可以复用,因此响应不需要依靠 Connection: keep-alive 才能成为长连接。该字段不能保证服务器一定保持 TCP 连接,服务器仍可能因为超时、资源限制或其他原因主动关闭连接。
如果服务器希望当前响应发送完成后关闭连接,可以返回:
Connection: close
HTTP/2 和 HTTP/3 不使用这些 HTTP/1.1 连接级字段。
10. ETag
ETag: "737060cd8c284d8af7ad3082f209582d"
ETag 是服务器为某个选定表示生成的不透明验证器,用于判断缓存中的表示是否仍然有效。它不是 URL 的固定 ID,也不要求必须由文件内容的 MD5 值生成。
客户端下一次请求资源时,可以通过 If-None-Match 携带之前的 ETag:
If-None-Match: "737060cd8c284d8af7ad3082f209582d"
如果资源没有变化,服务器可以返回 304 Not Modified;如果发生变化,则返回新的资源和新的 ETag。ETag 还可以使用弱验证器,例如 W/"abc",强 ETag 和弱 ETag 的比较语义不同。
11. Refresh
Refresh: 5; url=https://www.baidu.com
Refresh 是浏览器广泛支持的事实标准响应头,并不是 HTTP 标准重定向机制。示例中的 5 表示等待 5 秒后刷新或跳转,并不是固定默认值。
需要使用正式 HTTP 重定向时,应返回 3xx 状态码和 Location 响应头:
HTTP/1.1 302 Found
Location: https://www.baidu.com/
12. Access-Control-Allow-Origin
Access-Control-Allow-Origin 是 CORS 响应头,用于声明哪些 origin 可以读取当前响应。
Access-Control-Allow-Origin: *
* 表示允许任意 origin 的非凭据跨域请求读取响应。但当请求使用凭据模式时,不能同时使用 * 和 Access-Control-Allow-Credentials: true。
如果只允许某个站点,应返回完整的 origin,包括协议、主机和必要的端口:
Access-Control-Allow-Origin: https://www.baidu.com
不能只写 www.baidu.com,也不能简单写成多个 origin 逗号分隔的列表。服务器如果根据请求的 Origin 动态返回不同值,通常还应设置:
Vary: Origin
避免共享缓存把一个 origin 的 CORS 响应错误地复用给另一个 origin。
13. Access-Control-Allow-Methods
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
该响应头通常出现在 CORS 预检请求(OPTIONS)的响应中,用于告诉浏览器实际请求允许使用哪些 HTTP 方法。
它不是简单地让任意跨域请求都获得权限。对于复杂跨域请求,浏览器会先发送预检请求;服务器还可能需要通过 Access-Control-Allow-Headers 声明允许客户端携带的自定义请求头。简单请求不一定会触发预检,但仍然需要服务器返回正确的 Access-Control-Allow-Origin,浏览器才会允许脚本读取响应。
14. Access-Control-Allow-Credentials
Access-Control-Allow-Credentials: true
该响应头表示服务器允许浏览器在跨域请求中使用凭据,例如 Cookie、HTTP 认证信息或客户端证书。
它不会单独让浏览器自动发送 Cookie。请求端还需要显式启用凭据,例如 Fetch 使用 credentials: 'include',XHR 使用 withCredentials = true。同时,服务器必须返回具体的 Access-Control-Allow-Origin,不能使用 *,并且 Cookie 还要满足 SameSite、Secure、域名和路径等规则。
该字段的有效值是精确的小写字符串 true。如果服务器不允许凭据,可以不返回这个字段。
15. Content-Range
Content-Range: bytes 0-5/7877
Content-Range 通常用于 206 Partial Content 响应,表示本次响应在完整表示中的字节范围和完整长度。这里的 0-5 是包含首尾字节的范围,7877 是完整资源的长度。
如果完整长度未知,可以使用 *:
Content-Range: bytes 0-5/*
当请求范围无法满足时,服务器可能返回 416 Range Not Satisfiable,并使用类似下面的响应头告知完整长度:
Content-Range: bytes */7877
三、几个容易混淆的对应关系
| 请求头 | 常见响应头 | 作用 |
|---|---|---|
Accept | Content-Type | 协商响应媒体类型 |
Accept-Encoding | Content-Encoding | 协商和声明内容编码 |
Accept-Language | Content-Language | 协商和声明自然语言 |
Range | Content-Range | 请求和描述部分内容 |
If-None-Match | ETag | 基于实体标签进行缓存验证 |
If-Modified-Since | Last-Modified | 基于修改时间进行缓存验证 |
作者:晴天
原文链接:https://juejin.cn/post/6844903745004765198
来源:稀土掘金。著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。