HTTP 基础:方法、状态码与请求语义

HTTP 的核心特点

HTTP 是应用层请求—响应协议。它本身是无状态的,但可以借助 Cookie、Token 和服务端 Session 关联多次请求。

常用方法

方法常见用途安全幂等
GET获取资源
HEAD只获取响应头
POST创建或触发处理通常否
PUT整体创建或替换
PATCH部分更新不一定
DELETE删除资源
OPTIONS查询通信能力、CORS 预检

“安全”表示按协议语义不修改服务端状态;“幂等”表示执行一次和多次的预期效果相同,不代表每次响应完全相同。

请求结构与请求头

问题:HTTP 请求包括哪几部分?

**答案:**一个完整的 HTTP 请求通常包括请求行、请求头、空行和请求体四部分:

POST /api/users?page=1 HTTP/1.1   ← 请求行
Host: example.com                 ← 请求头
Content-Type: application/json
Authorization: Bearer <token>
                                   ← 空行,分隔请求头和请求体
{"name":"Alice"}                 ← 请求体
  1. 请求行:包括请求方法、请求目标和 HTTP 版本。请求目标通常包含路径和查询参数,例如 GET /users?page=1 HTTP/1.1
  2. 请求头:描述请求的元信息,例如目标主机、内容格式、认证信息、缓存条件和客户端能力。
  3. 空行:请求头结束的标志。即使没有请求体,也需要通过这个边界区分请求头和后续内容。
  4. 请求体:可选,用于携带提交的数据,常见格式有 JSON、表单、纯文本和文件 multipart。

注意:路径和查询参数属于请求目标的一部分,不属于请求体;GET 通常不使用请求体,POST、PUT、PATCH 更常通过请求体提交数据。

问题:常见的请求头及作用是什么?

**答案:**常见请求头可以按用途分为以下几类:

请求头作用
Host指定请求的目标域名和端口,HTTP/1.1 必需;同一 IP 承载多个站点时用于选择站点。
User-Agent描述客户端类型、操作系统和浏览器信息,服务端可用于兼容处理和统计。
Accept声明客户端可以接受的响应媒体类型,例如 application/json
Accept-Language声明客户端偏好的语言,服务端可据此返回不同语言内容。
Accept-Encoding声明支持的压缩算法,例如 gzipbr,服务端通常配合响应头 Content-Encoding
Content-Type声明请求体的数据格式,例如 application/jsonapplication/x-www-form-urlencoded
Content-Length声明请求体的字节长度;分块传输时可能改用 Transfer-Encoding: chunked
Authorization携带身份认证凭证,例如 Bearer Token 或 Basic 认证信息。
Cookie携带客户端保存的 Cookie,用于会话、登录状态和个性化信息。
Referer表示当前请求通常从哪个页面发起,可用于来源分析和部分安全校验。
Origin表示请求来源的协议、域名和端口,常用于 CORS 校验,尤其是跨域请求。
Cache-Control控制请求缓存行为,例如 no-cache 要求验证缓存,no-store 要求不使用缓存。
If-None-Match携带缓存的 ETag,配合协商缓存;资源未变化时服务端返回 304
If-Modified-Since携带资源上次修改时间,配合 Last-Modified 进行协商缓存。
ConnectionHTTP/1.x 中用于表达连接管理意图,例如 keep-aliveclose
Range请求资源的部分内容,常用于断点续传和大文件分段下载。

最容易混淆的是:Accept 描述“我希望接收什么响应”,Content-Type 描述“我发送的请求体是什么格式”;Authorization 负责认证凭证,Cookie 主要用于携带浏览器会话信息。

常见请求头详解

Host

Host: api.example.com:443

表示请求访问的域名和端口。HTTP/1.1 中通常是必需的。多个域名可以解析到同一个 IP,服务器会根据 Host 区分请求应该交给哪个站点或虚拟主机。

User-Agent

User-Agent: Mozilla/5.0 ... Chrome/120.0.0.0 Safari/537.36

描述发起请求的客户端类型、操作系统和浏览器版本,常用于访问统计、兼容性处理和问题排查。它不是可靠的身份认证信息,因为客户端可以伪造。

Accept

Accept: application/json, text/plain, */*

表示客户端能够处理、希望服务端返回的媒体类型。服务端可以根据它进行内容协商,并通过响应头 Content-Type 告知最终返回的格式。

Accept: application/json 表示希望返回 JSON;*/* 表示可以接受任意媒体类型。

Accept-Language

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

表示客户端偏好的自然语言及优先级。服务端可以据此选择中文或英文内容,响应中也可能通过 Content-Language 标识实际语言。它只是偏好信息,不代表用户一定有权限访问某种语言资源。

Accept-Encoding

Accept-Encoding: gzip, deflate, br

表示客户端支持的响应内容编码方式。服务端如果选择压缩,会通过响应头 Content-Encoding: brContent-Encoding: gzip 说明压缩算法。压缩可以减少传输体积,但会增加压缩和解压 CPU 消耗。

Content-Type

Content-Type: application/json

描述当前请求体的媒体类型,服务端据此决定如何解析请求体。常见值包括:

  • application/json:JSON 数据。
  • application/x-www-form-urlencoded:键值对表单数据。
  • multipart/form-data; boundary=...:表单和文件上传。
  • text/plain:纯文本。

它描述的是“我发送的数据是什么格式”,不是“我希望接收什么格式”;后者由 Accept 表示。

Content-Length

Content-Length: 27

表示请求体的字节数,不是字符数。服务端可以根据它判断请求体何时结束。使用分块传输时,可能改用 Transfer-Encoding: chunked,此时请求体会分成多个数据块发送。

Authorization

Authorization: Bearer eyJ...

携带身份认证凭证。常见形式有:

  • Bearer <token>:携带 Token,常用于 OAuth 2.0 和 JWT。
  • Basic <base64>:携带用户名和密码的 Base64 编码结果。

Base64 不是加密方式,认证信息必须通过 HTTPS 传输,并且服务端仍需校验凭证有效期、权限和签名。

Cookie: sessionId=abc123; theme=dark

携带当前域名下符合条件的 Cookie,常用于会话标识、登录状态和用户偏好。Cookie 通常由服务端通过响应头 Set-Cookie 设置,浏览器后续请求会自动携带符合 Domain、Path、Secure 和 SameSite 条件的 Cookie。

不要把大量业务数据直接放进 Cookie,因为 Cookie 会在符合条件的每次请求中发送,增加请求体积。

Referer

Referer: https://example.com/products

表示当前请求通常从哪个页面跳转或发起,用于来源分析、防盗链和部分安全校验。它可能受 Referrer-Policy 控制,也可能因为隐私策略被截断或不发送,因此不能作为唯一的安全依据。

Origin

Origin: https://app.example.com

表示请求来源的协议、域名和端口。它是 CORS 校验的重要依据,跨域请求和部分同源请求可能携带该请求头。服务端需要校验允许的 Origin,不能简单地对任意 Origin 都返回 Access-Control-Allow-Origin: *,尤其是涉及凭证时。

Cache-Control

Cache-Control: no-cache

控制请求的缓存行为:

  • no-cache:可以使用缓存,但使用前必须向服务端验证。
  • no-store:不要读取或保存缓存。
  • max-age=0:缓存立即视为过期,通常需要重新验证。
  • only-if-cached:只使用已有缓存,不访问网络,常用于特殊缓存场景。

请求头的 Cache-Control 与响应头的 Cache-Control 作用对象不同:前者表达客户端本次请求的缓存要求,后者表达服务端返回资源的缓存策略。

If-None-Match

If-None-Match: "686897696a7c876b7e"

携带客户端缓存资源的 ETag,用于协商缓存。服务端比较当前资源的 ETag:如果没有变化,返回 304 Not Modified;如果发生变化,返回 200 和新的资源内容。

If-Modified-Since

If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT

携带客户端缓存资源的最后修改时间,用于和响应头 Last-Modified 配合进行协商缓存。资源未修改时返回 304。通常服务端优先使用 If-None-Match,只有没有可用 ETag 时才依赖该字段。

Connection

Connection: keep-alive

在 HTTP/1.x 中表达连接管理意图。keep-alive 表示请求完成后尽量复用 TCP 连接,close 表示响应完成后关闭连接。HTTP/2 和 HTTP/3 使用其他机制管理连接,不能简单照搬 HTTP/1.1 的逐跳请求头语义。

Range

Range: bytes=1000-1999

请求资源的部分字节,常用于断点续传、视频拖动和大文件分段下载。服务端支持时返回 206 Partial Content,并通过 Content-Range 说明本次返回的范围;不支持时可能忽略 Range 并返回完整资源。

GET 与 POST 常见误区

  • HTTP 规范没有用“能否有请求体”简单区分 GET 和 POST,但 GET 请求体缺乏通用语义,代理和框架支持也不一致。
  • URL 长度限制主要来自浏览器、服务器和代理实现,不是 HTTP 协议统一规定。
  • POST 不天然比 GET 安全;机密性依赖 HTTPS,权限依赖鉴权和服务端校验。
  • GET 通常可缓存、可收藏、可重放,POST 默认缓存支持较弱。

状态码

2xx 成功

  • 200 OK:请求成功。
  • 201 Created:资源创建成功,常配合 Location
  • 204 No Content:成功但无响应体。

3xx 重定向与缓存

  • 301308:永久重定向。
  • 302303:实践中常把后续请求改为 GET。
  • 307308:明确要求保留原方法和请求体。
  • 304 Not Modified:协商缓存命中,不携带新的资源实体。

4xx 客户端问题

  • 400 Bad Request:请求格式或参数错误。
  • 401 Unauthorized:实际含义更接近“未认证”。
  • 403 Forbidden:身份已知但没有权限。
  • 404 Not Found:资源不存在。
  • 409 Conflict:资源状态冲突。
  • 429 Too Many Requests:请求过多。

5xx 服务端问题

  • 500 Internal Server Error:服务内部错误。
  • 502 Bad Gateway:网关收到无效上游响应。
  • 503 Service Unavailable:临时不可用。
  • 504 Gateway Timeout:网关等待上游超时。

常用请求头与响应头

  • 内容协商:AcceptAccept-LanguageContent-Type
  • 缓存:Cache-ControlETagIf-None-MatchLast-Modified
  • 身份与会话:AuthorizationCookieSet-Cookie
  • 跳转和资源:LocationContent-Disposition
  • 跨域:OriginAccess-Control-Allow-Origin

Content-Type 描述当前消息体格式,Accept 描述客户端希望接收的格式。

HTTP/1.1、HTTP/2 与 HTTP/3

能力HTTP/1.1HTTP/2HTTP/3
传输基础TCPTCPQUIC/UDP
多路复用不完善支持支持
头部压缩无标准压缩HPACKQPACK
传输层队头阻塞不同流之间显著改善
连接迁移不支持不支持支持

高频场景题

401 和 403 如何选择?

未登录、Token 无效通常返回 401;已经识别用户但权限不足返回 403。前端不应仅通过隐藏按钮实现权限控制,服务端必须再次鉴权。

POST 如何防止重复提交?

前端可以禁用按钮和请求去重,但最终保证通常依赖服务端幂等键、唯一约束或状态机。