HTTP 报文结构与状态码

HTTP 请求/响应报文的组成部分及常见状态码含义

问题

描述 HTTP 报文的结构,并解释常见状态码(200, 301, 302, 304, 400, 401, 403, 404, 500, 502)的含义。

解答

HTTP 报文结构

HTTP 报文分为请求报文和响应报文,都由三部分组成:

┌─────────────────────────────┐
│  起始行(请求行/响应行)      │
├─────────────────────────────┤
│  头部(Headers)             │
├─────────────────────────────┤
│  空行                        │
├─────────────────────────────┤
│  实体(Body)                │
└─────────────────────────────┘

请求报文

POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer token123
Content-Length: 27

{"name":"John","age":25}

请求行方法 + 路径 + HTTP版本

POST /api/users HTTP/1.1

响应报文

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 45
Cache-Control: max-age=3600

{"id":1,"name":"John","age":25}

响应行HTTP版本 + 状态码 + 状态描述

HTTP/1.1 200 OK

常见请求头

头部说明
Host目标主机
Content-Type请求体类型
Authorization认证信息
Cookie客户端 Cookie
User-Agent客户端标识
Accept可接受的响应类型

常见响应头

头部说明
Content-Type响应体类型
Content-Length响应体长度
Set-Cookie设置 Cookie
Cache-Control缓存策略
Location重定向地址

常见状态码

2xx 成功

状态码含义
200 OK请求成功

3xx 重定向

状态码含义
301 Moved Permanently永久重定向,资源已永久移动到新 URL
302 Found临时重定向,资源临时移动
304 Not Modified资源未修改,使用缓存
// 301 vs 302 的区别
// 301: 浏览器会缓存重定向,下次直接访问新地址
// 302: 每次都会先请求原地址

// 304 场景:协商缓存命中
// 请求头带 If-Modified-Since 或 If-None-Match
// 服务器验证资源未变化,返回 304

4xx 客户端错误

状态码含义
400 Bad Request请求语法错误,服务器无法理解
401 Unauthorized未认证,需要登录
403 Forbidden已认证但无权限访问
404 Not Found资源不存在
// 401 vs 403 的区别
// 401: 你是谁?(未登录)
// 403: 我知道你是谁,但你没权限(已登录但权限不足)

5xx 服务器错误

状态码含义
500 Internal Server Error服务器内部错误
502 Bad Gateway网关/代理收到上游服务器的无效响应
// 500 vs 502 的区别
// 500: 服务器自身代码出错
// 502: 服务器作为网关,上游服务器挂了或返回异常

使用 fetch 处理不同状态码

async function request(url) {
  const response = await fetch(url);
  
  switch (response.status) {
    case 200:
      return response.json();
    case 301:
    case 302:
      // fetch 会自动跟随重定向
      console.log('重定向到:', response.url);
      return response.json();
    case 304:
      // 使用缓存数据
      return getCachedData(url);
    case 400:
      throw new Error('请求参数错误');
    case 401:
      // 跳转登录
      redirectToLogin();
      break;
    case 403:
      throw new Error('没有访问权限');
    case 404:
      throw new Error('资源不存在');
    case 500:
      throw new Error('服务器错误');
    case 502:
      throw new Error('网关错误,请稍后重试');
    default:
      throw new Error(`未知错误: ${response.status}`);
  }
}

关键点

  • HTTP 报文由三部分组成:起始行、头部、实体,头部和实体之间有空行分隔
  • 301 是永久重定向(浏览器缓存),302 是临时重定向(每次请求原地址)
  • 304 表示协商缓存命中,服务器告诉客户端使用本地缓存
  • 401 是未认证(需登录),403 是无权限(已登录但权限不足)
  • 500 是服务器自身错误,502 是网关收到上游无效响应