HTTP 状态码详解:1xx ~ 5xx 完整速查手册

2024-07-14 编程开发

HTTP 状态码是服务器对客户端请求的"暗号"。无论是前端调试、后端接口开发还是运维排障,看懂状态码都是基本功。本文按 1xx~5xx 分类,逐一讲解常用状态码的含义、典型场景、调试方法,并附带 curl 测试命令和 Nginx/Express 配置示例。

一、状态码总览

类别 范围 含义 常见状态码
1xx 100 ~ 103 信息响应——请求已收到,继续处理 100, 101
2xx 200 ~ 226 成功——请求已成功处理 200, 201, 204, 206
3xx 300 ~ 308 重定向——需要进一步操作 301, 302, 304, 307, 308
4xx 400 ~ 451 客户端错误——请求有问题 400, 401, 403, 404, 405, 429
5xx 500 ~ 511 服务端错误——服务器处理失败 500, 502, 503, 504

二、1xx:信息响应

100 Continue

客户端发送带 Expect: 100-continue 头的请求时,服务器返回 100 表示"可以继续发送请求体"。常用于大文件上传前先探测服务器是否愿意接收。

# curl 模拟 100-continue
curl -X POST -H "Expect: 100-continue" \
  -H "Content-Type: application/json" \
  -d '{"large":"payload"}' https://api.example.com/upload

101 Switching Protocols

WebSocket 握手时,服务器返回 101 表示协议切换。

# WebSocket 升级请求
curl -i -N -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  http://localhost:8080

# 响应:
# HTTP/1.1 101 Switching Protocols
# Upgrade: websocket
# Connection: Upgrade

三、2xx:成功响应

200 OK

请求成功,最常见。GET 返回资源,POST 返回处理结果。

curl -i https://api.example.com/users/1
# HTTP/1.1 200 OK

201 Created

POST 创建资源成功后返回,通常会在 Location 头中携带新资源的 URL。

curl -i -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"张三"}' https://api.example.com/users

# HTTP/1.1 201 Created
# Location: /users/42

Express 示例:

app.post('/users', async (req, res) => {
  const user = await User.create(req.body);
  res.status(201)
     .location(`/users/${user.id}`)
     .json(user);
});

204 No Content

请求成功但无返回体。常见于 DELETE 或 PUT 更新操作。

curl -i -X DELETE https://api.example.com/users/42
# HTTP/1.1 204 No Content

206 Partial Content

断点续传、分片下载。配合 Range 头使用。

# 只下载前 1024 字节
curl -i -H "Range: bytes=0-1023" https://example.com/video.mp4
# HTTP/1.1 206 Partial Content
# Content-Range: bytes 0-1023/10485760
# Content-Length: 1024

四、3xx:重定向

301 Moved Permanently(永久重定向)

资源已永久迁移到新 URL。浏览器会缓存,搜索引擎会更新索引。

302 Found(临时重定向)

资源临时移动。浏览器不缓存,下次仍请求原 URL。

特性 301 永久重定向 302 临时重定向
浏览器缓存 会缓存 不缓存
SEO 影响 权重转移给新 URL 权重保留在原 URL
请求方法变化 POST 可能变 GET POST 可能变 GET
使用场景 域名迁移、HTTPS 强制 活动页、维护页跳转

⚠️ 注意:301/302 在浏览器中有个著名坑——POST 请求被重定向后可能变成 GET 请求。如果希望保持请求方法不变,使用 307/308。

307 Temporary Redirect / 308 Permanent Redirect

与 302/301 的区别:严格保持请求方法和请求体不变。

# Nginx:301 永久重定向到 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

# Nginx:302 临时维护页面
location /app {
    return 302 /maintenance.html;
}

# Nginx:308 保持 POST 方法
location /api/v1 {
    return 308 /api/v2$request_uri;
}

304 Not Modified

缓存验证。客户端携带 If-None-Match(ETag)或 If-Modified-Since 请求,服务器判断资源未变化则返回 304,客户端使用本地缓存。

curl -i -H "If-None-Match: \"abc123\"" https://example.com/style.css
# HTTP/1.1 304 Not Modified

Express 中启用 ETag:

// Express 默认启用 ETag,也可手动控制
app.set('etag', 'strong');  // 或 'weak'

app.get('/data', (req, res) => {
  const data = { time: Date.now() };
  // Express 自动生成 ETag 并处理 304
  res.json(data);
});

五、4xx:客户端错误

400 Bad Request

请求报文语法错误,如 JSON 格式不正确、参数缺失等。

curl -i -X POST \
  -H "Content-Type: application/json" \
  -d "这不是JSON" https://api.example.com/users
# HTTP/1.1 400 Bad Request

401 Unauthorized

未认证——需要提供有效凭证。常见于未登录或 Token 过期。

curl -i https://api.example.com/admin
# HTTP/1.1 401 Unauthorized
# WWW-Authenticate: Bearer realm="api"

403 Forbidden

已认证但无权限——"我知道你是谁,但你不能访问这个资源"。

状态码 含义 类比
401 Unauthorized 没带证件 进大楼没刷卡
403 Forbidden 证件不对口 刷了卡但没权限进这个房间

404 Not Found

资源不存在。注意:RESTful 接口中,有时也返回 404 来隐藏资源是否存在(避免枚举攻击)。

curl -i https://api.example.com/users/99999
# HTTP/1.1 404 Not Found

405 Method Not Allowed

HTTP 方法不允许。比如对只读接口发 POST。

curl -i -X POST https://api.example.com/health
# HTTP/1.1 405 Method Not Allowed
# Allow: GET, HEAD

429 Too Many Requests

触发频率限制。响应头中通常包含 Retry-After 或 X-RateLimit-* 信息。

# 模拟触发限流
for i in $(seq 1 100); do
  curl -s -o /dev/null -w "%{http_code}\n" https://api.example.com/data &
done

# HTTP/1.1 429 Too Many Requests
# Retry-After: 60
# X-RateLimit-Limit: 100
# X-RateLimit-Remaining: 0
# X-RateLimit-Reset: 1720950000

Express 限流中间件:

const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 分钟
  max: 100,                   // 最多 100 次
  standardHeaders: true,
  legacyHeaders: false,
  message: { error: '请求过于频繁,请稍后再试' }
});

app.use('/api/', limiter);

Nginx 限流:

# 限流区域:每秒 10 个请求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

server {
    location /api/ {
        limit_req zone=mylimit burst=20 nodelay;
        proxy_pass http://backend;
    }
}

六、5xx:服务端错误

500 Internal Server Error

服务端代码异常(未捕获的错误)。

// ❌ 危险:裸奔的错误处理
app.get('/data', async (req, res) => {
  const result = await riskyOperation(); // 可能抛异常 → 500
  res.json(result);
});

// ✅ 安全:全局错误处理中间件
app.use((err, req, res, next) => {
  console.error('服务器错误:', err.stack);
  res.status(500).json({
    error: '服务器内部错误',
    requestId: req.id  // 方便关联日志排查
  });
});

502 Bad Gateway

网关或代理服务器收到上游无效响应。常见于:

  • 后端服务挂了
  • 后端返回了格式错误的响应
  • 反向代理配置的 upstream 不可达
# 自定义 502 错误页
error_page 502 /502.html;
location = /502.html {
    root /usr/share/nginx/html;
}

503 Service Unavailable

服务器暂时不可用——过载或维护中。应返回 Retry-After 头。

curl -i https://example.com
# HTTP/1.1 503 Service Unavailable
# Retry-After: 3600

504 Gateway Timeout

网关超时——上游服务器响应太慢。

# 延长上游超时
location /slow-api/ {
    proxy_pass http://backend;
    proxy_read_timeout 120s;
    proxy_connect_timeout 10s;
}

七、浏览器 DevTools 排查技巧

Network 面板快速诊断

  1. 打开 DevTools → Network 标签
  2. 刷新页面,按 Status 列排序
  3. 红色状态码(4xx/5xx)重点关注

关键检查项

现象 排查方向
大量红色 404 静态资源路径错误、CDN 配置问题
间歇性 502/504 后端负载过高、连接池耗尽
AJAX 请求 401 Token 过期、Cookie 丢失
跨域请求失败 CORS 头缺失,看 Console 的 CORS 错误
请求发出后立即 400 检查 Request Payload 格式

curl 调试三板斧

# 1. 只看状态码
curl -o /dev/null -s -w "%{http_code}\n" https://example.com

# 2. 看完整响应头 + 体
curl -i https://example.com

# 3. 看详细过程(含 DNS、TCP、TLS 握手时间)
curl -w "@curl-format.txt" -o /dev/null -s https://example.com

# curl-format.txt 内容:
#   time_namelookup:  %{time_namelookup}\n
#   time_connect:     %{time_connect}\n
#   time_appconnect:  %{time_appconnect}\n
#   time_pretransfer: %{time_pretransfer}\n
#   time_redirect:    %{time_redirect}\n
#   time_starttransfer: %{time_starttransfer}\n
#   time_total:       %{time_total}\n

八、速查表

状态码 含义 一句话记忆
200 OK 一切正常
201 Created 新建成功,去 Location 找
204 No Content 成功但没话说
301 Moved Permanently 搬家了,新地址记好
302 Found 临时换个地方
304 Not Modified 用你手里的缓存
400 Bad Request 你发的啥我看不懂
401 Unauthorized 你没带证件
403 Forbidden 有证件也没用
404 Not Found 找不到这个
429 Too Many Requests 你太快了,慢点
500 Internal Server Error 我炸了
502 Bad Gateway 上游炸了
503 Service Unavailable 在维护,等会儿再来
504 Gateway Timeout 上游响应太慢了

总结

  • 2xx — 成功了,按语义区分 200/201/204/206
  • 3xx — 重定向,301/302 改变方法体,307/308 保留方法体,304 用于缓存
  • 4xx — 你的问题,401 vs 403 分清认证和授权
  • 5xx — 我的问题,502/504 通常是反向代理层的锅

掌握这些状态码,配合 curl 和浏览器 DevTools,排障效率提升一个数量级。