HTTP协议基础总结

1. HTTP 协议基础

目录

1.1 什么是 HTTP?

HTTP(HyperText Transfer Protocol,超文本传输协议)是 客户端与服务器之间通信的应用层协议。它基于 请求-响应 模型,默认使用 TCP 作为传输层。

一次完整的请求流程

  1. 浏览器解析出请求的域名。
  2. 通过DNS(域名系统)获取服务器的IP地址。
  3. 与服务器建立TCP连接(如果是HTTPS,还需进行TLS握手)。
  4. 构建并发送HTTP请求报文。
  5. 服务器接收、解析并处理请求,然后返回HTTP响应报文。
  6. 浏览器解析响应,并关闭或复用TCP连接。

在这里插入图片描述

1.2 HTTP 请求结构

一次 HTTP 请求由三部分组成:

部分说明示例
请求行方法 + URL + 协议版本GET /api/users HTTP/1.1
请求头元数据(键值对)Content-Type: application/json
请求体可选,携带数据{"name": "张三"}

完整请求示例:

POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/json

{
  "name": "张三",
  "email": "zhangsan@example.com"
}

1.3 HTTP 响应结构

部分说明示例
状态行协议版本 + 状态码 + 描述HTTP/1.1 200 OK
响应头元数据Content-Type: application/json
响应体实际返回的数据{"id": 1, "name": "张三"}

完整响应示例:

HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": 1,
  "name": "张三",
  "email": "zhangsan@example.com"
}

1.4 常见请求头与响应头

HTTP 头(Header)是键值对形式的元数据,不参与业务 Body,但决定服务端如何解析请求、客户端如何处理响应。格式统一为:

Header-Name: value

下面按请求头响应头分开说明日常开发中最常用的字段。

常见请求头
Content-Type
项目说明
作用告诉服务器:请求体(Body)是什么格式,服务端据此选择 JSON 解析器、表单解析器或文件处理器
何时需要POST / PUT / PATCH 等带 Body 的请求;GET 通常不需要
示例Content-Type: application/json
POST /api/users HTTP/1.1
Content-Type: application/json

{"name": "张三", "email": "zhangsan@example.com"}

常见取值包括 application/jsonapplication/x-www-form-urlencodedmultipart/form-data 等,各格式的 Body 写法与代码示例见 §1.4.1 Content-Type 详解

Authorization
项目说明
作用携带身份认证凭证,证明「我是谁」,用于访问需要登录或鉴权的接口
常见格式Bearer <Token>(JWT 最常见)、Basic <Base64>(用户名密码)
示例Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
GET /api/orders HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
  • Token 无效或过期时,服务器通常返回 401 Unauthorized
  • 前端一般在登录成功后保存 Token,之后每次请求自动附加此头
  • 注意: 不要把 Token 写在 URL 里,应放在 Header 中
User-Agent
项目说明
作用标识发起请求的客户端类型(浏览器、爬虫、移动端 App、Postman 等)
谁发送浏览器通常自动添加;后端可据此做统计、兼容性处理或反爬策略
示例User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
GET /api/products HTTP/1.1
User-Agent: MyApp/1.0 (Android 14)
  • 一般无需手动设置;调用 API 时若服务端有 UA 校验,需按文档指定
  • 伪造 UA 可能触发风控,生产环境应使用真实、规范的值
Accept
项目说明
作用告诉服务器:客户端希望收到什么格式的响应(内容协商)
与 Content-Type 区别Accept 描述「我能接受什么响应」;请求侧的 Content-Type 描述「我发送的 Body 是什么」
示例Accept: application/json
GET /api/users/1 HTTP/1.1
Accept: application/json

常见取值:

Accept 值含义
application/json期望 JSON(REST API 最常用)
text/html期望 HTML 页面(浏览器访问网页)
application/xml期望 XML
*/*任意格式均可(默认值之一)

可同时声明多种格式并带优先级,例如:Accept: application/json, text/plain;q=0.9q 为权重,越大越优先)。

Cache-Control
项目说明
作用控制缓存行为:是否使用缓存、缓存多久、是否必须向源站验证
请求侧含义客户端声明自己对缓存的要求
示例Cache-Control: no-cache
GET /api/profile HTTP/1.1
Cache-Control: no-cache

请求侧常见指令:

指令含义
no-cache可以使用缓存,但使用前必须向服务器确认是否仍有效
no-store不要存储任何缓存(敏感数据)
max-age=0立即视为过期,需重新验证

调试接口时,可在浏览器 DevTools 中勾选 Disable cache,等效于强制跳过本地缓存。

Connection
项目说明
作用控制TCP 连接是否保持(长连接 / 短连接)
HTTP/1.1 默认Connection: keep-alive(同一 TCP 连接可复用,减少握手开销)
示例Connection: keep-aliveConnection: close
GET /api/data HTTP/1.1
Connection: keep-alive
含义
keep-alive请求完成后不立即关闭 TCP 连接,后续请求可复用
close本次响应结束后关闭连接(HTTP/1.0 风格)
  • 空闲超时 (Idle Timeout):这是最主要的方式。如果连接在指定时间内没有新请求,服务器就会主动关闭它常见默认值:Nginx 默认 75秒,Tomcat 默认 30秒,Node.js 默认 5分钟
  • 最大请求数限制 (Max Requests):为防止单一连接处理过多请求,服务器会限制其最大使用次数,达到上限后关闭。常见如 Nginx 默认 100次
Accept-Encoding
项目说明
作用告诉服务器:客户端支持哪些响应压缩算法,服务器可对响应 Body 压缩后再传输,节省带宽
示例Accept-Encoding: gzip, deflate, br
GET /api/large-report HTTP/1.1
Accept-Encoding: gzip, deflate, br
编码说明
gzip最普遍,几乎所有服务器和浏览器支持
deflate较少单独使用
brBrotli 压缩,现代浏览器支持,压缩率通常更好

浏览器会自动发送此头;服务端若返回压缩内容,会在响应头中用 Content-Encoding: gzip 标明,客户端自动解压。


常见响应头

响应头由服务器返回,描述响应本身的属性。以下与上文请求头一一对应或配合使用。

Content-Type(响应)
项目说明
作用告诉客户端:响应体(Body)是什么格式,浏览器或代码据此决定如何解析
示例Content-Type: application/json; charset=UTF-8
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

{"id": 1, "name": "张三"}
  • 返回 JSON 接口务必设置为 application/json,否则前端可能无法正确解析
Content-Disposition(响应)
项目说明
作用告诉浏览器如何处理响应 Body:在页面内嵌展示,还是作为附件下载;下载时可指定默认文件名
常见取值inline(内联展示)、attachment(触发下载)
示例Content-Disposition: attachment; filename="report.pdf"
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"

(PDF 二进制内容)
取值 / 参数含义
inline在浏览器内直接打开(如 PDF 预览、图片显示)
attachment提示用户保存为文件,弹出「另存为」或使用默认文件名下载
filename="..."建议的下载文件名(中文建议配合 filename*=UTF-8'' 编码)

典型场景:

  • 导出 Excel / PDFContent-Disposition: attachment; filename="订单列表.xlsx"
  • 在线预览 PDFContent-Disposition: inline + Content-Type: application/pdf
  • 接口返回文件流:常与 Content-Type: application/octet-stream 配合使用
HTTP/1.1 200 OK
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="export.xlsx"
Cache-Control(响应)
项目说明
作用告诉浏览器和中间代理:此响应能否缓存、缓存多久
示例Cache-Control: max-age=3600, public
HTTP/1.1 200 OK
Cache-Control: max-age=3600, public
Content-Type: application/json

{"list": [...]}

响应侧常见指令:

指令含义
public可被浏览器和 CDN 等任意缓存
private仅浏览器可缓存,CDN 不应缓存(含用户私有数据)
max-age=3600缓存 3600 秒(1 小时)内可直接使用,无需再问服务器
no-store禁止存储(登录态、支付等敏感接口)
no-cache可存但必须每次向源站验证

静态资源(JS/CSS/图片)常设较长 max-age;动态 API 数据多用 no-cacheno-store

Connection(响应)
项目说明
作用告知客户端本次响应后是否关闭 TCP 连接
示例Connection: keep-alive
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json

通常与请求侧的 Connection 一致;HTTP/1.1 下多数场景为 keep-alive,由服务器或反向代理(Nginx)统一管理。

Content-Encoding(响应,配合 Accept-Encoding)
项目说明
作用标明响应 Body 使用的压缩方式,与请求头 Accept-Encoding 配合
示例Content-Encoding: gzip
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: application/json

(gzip 压缩后的二进制 Body,浏览器会自动解压)

客户端在 Accept-Encoding 中声明支持 gzip 后,服务器可选择压缩响应;若未压缩,则不发送此头


请求头与响应头对照速查:

头名称请求响应核心作用
Content-Type声明 Body 的媒体类型
Authorization携带认证凭证
User-Agent标识客户端类型
Accept指定期望的响应格式
Cache-Control控制缓存策略
Connection控制 TCP 连接是否保持
Accept-Encoding声明支持的压缩算法
Content-Encoding标明响应已采用的压缩方式
Content-Disposition控制内联展示或附件下载、文件名
1.4.1 Content-Type 详解:常见类型与传参方式

Content-Type 请求头声明 请求体(Body)的数据格式,服务端据此解析参数。没有 Body 的请求(如 GET)通常不需要设置此头。

格式说明
Content-Type: 主类型/子类型[; 参数=值]

示例:Content-Type: application/json; charset=UTF-8

常见类型速查
Content-Type用途参数位置典型场景
application/jsonJSON 格式请求体 BodyREST API、前后端分离
application/x-www-form-urlencodedURL 编码键值对请求体 Body传统表单、OAuth Token
multipart/form-data多部分表单请求体 Body(分段)文件上传、含文件的表单
text/plain纯文本请求体 Body简单文本、 Webhook
application/xmlXML 格式请求体 BodySOAP、旧式接口
application/octet-stream二进制流请求体 Body(原始字节)文件直传、下载
text/htmlHTML 文档请求体 Body少见(多为响应)

JSON 对象/数组

简单键值对

XML

原始二进制

选择 Content-Type

有文件上传?

multipart/form-data

数据结构?

application/json

application/x-www-form-urlencoded

application/xml

application/octet-stream


1. application/json(最常用)

请求头:

Content-Type: application/json

Body 格式: JSON 对象或数组

请求示例:

POST /api/users HTTP/1.1
Content-Type: application/json

{
  "name": "张三",
  "email": "zhangsan@example.com",
  "age": 25,
  "tags": ["vip", "active"]
}

JavaScript(fetch):

fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: '张三',
    email: 'zhangsan@example.com'
  })
});

注意:

  • 嵌套对象、数组直接写在 JSON 中
  • 数字、布尔值不要加引号
  • 中文无需额外编码(UTF-8 默认)

2. application/x-www-form-urlencoded

请求头:

Content-Type: application/x-www-form-urlencoded

Body 格式: key1=value1&key2=value2,特殊字符 URL 编码

字符编码后
空格+%20
&%26
=%3D
中文%E4%B8%AD%E6%96%87

请求示例:

POST /api/login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=zhangsan&password=123456&remember=true

JavaScript:

// 方式 1:URLSearchParams(推荐)
const params = new URLSearchParams();
params.append('username', 'zhangsan');
params.append('password', '123456');

fetch('/api/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: params.toString()
});

// 方式 2:手动拼接
const body = 'username=zhangsan&password=' + encodeURIComponent('123456');

与 JSON 对比:

对比项form-urlencodedJSON
嵌套对象不支持(需 user[name] 约定)原生支持
数组需重复 key原生支持
文件不支持不支持(需 multipart)
可读性简单键值对直观结构复杂时更清晰

3. multipart/form-data(文件上传)

请求头:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

boundary 是分隔各字段的随机字符串,由客户端自动生成,不要手动写固定值。

Body 格式: 多个「部分(Part)」用 boundary 分隔,每部分可含普通字段或文件

POST /api/upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----Boundary123

------Boundary123
Content-Disposition: form-data; name="title"

我的文档
------Boundary123
Content-Disposition: form-data; name="file"; filename="report.pdf"

<二进制文件内容>
------Boundary123--

JavaScript(FormData,无需手动设 Content-Type):

const formData = new FormData();
formData.append('title', '我的文档');
formData.append('file', fileInput.files[0]);  // File 对象

fetch('/api/upload', {
  method: 'POST',
  body: formData
  // ⚠️ 不要手动设置 Content-Type,浏览器会自动加 boundary
});

字段结构说明:

部分说明
Content-Disposition: form-data; name="字段名"普通文本字段
Content-Disposition: form-data; name="字段名"; filename="文件名"文件字段
空行后的内容字段值或文件二进制

注意:

  • 同时传文件和普通字段时使用
  • 使用 FormData不要手动设置 Content-Type(boundary 由浏览器生成)
  • Postman 选 form-data 类型即可

4. text/plain

请求头:

Content-Type: text/plain

Body 格式: 纯文本字符串,无结构

POST /api/webhook HTTP/1.1
Content-Type: text/plain

Hello, this is a plain text message.

JavaScript:

fetch('/api/webhook', {
  method: 'POST',
  headers: { 'Content-Type': 'text/plain' },
  body: 'Hello, this is a plain text message.'
});

5. application/xml

请求头:

Content-Type: application/xml

Body 格式: XML 文档

POST /api/soap HTTP/1.1
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<user>
  <name>张三</name>
  <email>zhangsan@example.com</email>
</user>

JavaScript:

const xml = `<?xml version="1.0" encoding="UTF-8"?>
<user><name>张三</name></user>`;

fetch('/api/soap', {
  method: 'POST',
  headers: { 'Content-Type': 'application/xml' },
  body: xml
});

6. application/octet-stream

请求头:

Content-Type: application/octet-stream

Body 格式: 原始二进制字节流(无结构)

// 上传原始文件字节
const buffer = await file.arrayBuffer();

fetch('/api/files', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/octet-stream',
    'Content-Disposition': `attachment; filename="${file.name}"`
  },
  body: buffer
});

典型场景: 大文件直传、对象存储 PUT、固件升级包上传



各类型完整对比
类型结构嵌套/数组文件编码REST API 常用
application/jsonJSONUTF-8⭐⭐⭐ 最常用
application/x-www-form-urlencoded键值对URL 编码⭐⭐ 登录/表单
multipart/form-data多段✅(多字段)每段独立⭐⭐ 上传
text/plain纯文本文本⭐ 少见
application/xmlXMLUTF-8⭐ SOAP 遗留
application/octet-stream二进制原始字节⭐ 直传
常见错误与排查
错误现象原因解决
415 Unsupported Media Type服务端不支持该 Content-Type对照 API 文档改用正确类型
400 + JSON 解析失败发了 JSON 但 Content-Type 是 form改为 application/json
后端收到空 Body用了 JSON 但 Content-Type 是 form-urlencoded统一类型与 Body 格式
文件上传失败手动设置了 multipart 的 Content-Type 但 boundary 错误用 FormData,让浏览器自动设置
中文乱码缺少 charset; charset=UTF-8
Postman / Apifox 对照
工具中的 Body 类型对应 Content-Type
none无 Body
form-datamultipart/form-data
x-www-form-urlencodedapplication/x-www-form-urlencoded
raw → JSONapplication/json
raw → XMLapplication/xml
raw → Texttext/plain
binaryapplication/octet-stream

1.5 HTTP 方法

方法语义是否幂等是否有请求体
GET获取资源
POST创建资源
PUT全量替换资源
PATCH部分更新资源
DELETE删除资源
HEAD同 GET,但只返回响应头
OPTIONS查询服务器支持的方法(含浏览器预检)

幂等:多次相同请求产生的效果与一次相同。GET、PUT、DELETE 通常是幂等的;POST 不是。

1 . GET(获取资源)
  • 前端 Fetch
// 路径参数
fetch('/api/users/123');
// 查询参数(手动拼URL)
fetch('/api/users?page=1&size=10');
  • 后端 Spring Boot
@GetMapping("/users/{id}")
public User get(@PathVariable Long id) { return service.get(id); }
@GetMapping("/users")
public List<User> list(@RequestParam int page, @RequestParam int size) { 
    return service.list(page, size); 
}

2. POST(创建资源)
  • 前端 Fetch
fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: '张三', age: 25 })
});
  • 后端 Spring Boot
@PostMapping("/users")
public User create(@RequestBody UserDto dto) { 
    return service.save(dto); 
}


3. PUT(全量更新/替换)
  • 前端 Fetch
fetch('/api/users/123', {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: '张三新名', age: 30, email: 'new@xx.com' }) // 必须传全量字段
});
  • 后端 Spring Boot
@PutMapping("/users/{id}")
public User update(@PathVariable Long id, @RequestBody UserDto dto) {
    return service.fullUpdate(id, dto); // 全量覆盖
}

4. PATCH(部分更新)
  • 前端 Fetch
fetch('/api/users/123', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'new\_email@xx.com' }) // 只传要改的字段
});
  • 后端 Spring Boot
@PatchMapping("/users/{id}")
public User patch(@PathVariable Long id, @RequestBody Map<String, Object> patch) {
    return service.partialUpdate(id, patch); // 只更新传入的非空字段
}


5. DELETE(删除资源)
  • 前端 Fetch(参数放 URL,禁止放 Body
// 删除单个
fetch('/api/users/123', { method: 'DELETE' });
// 批量删除(Query传参)
fetch('/api/users?ids=1&ids=2&ids=3', { method: 'DELETE' });
  • 后端 Spring Boot
@DeleteMapping("/users/{id}")
public ResponseEntity<Void\> delete(@PathVariable Long id) {
    service.delete(id);
    return ResponseEntity.noContent().build(); // 返回 204
}
@DeleteMapping("/users")
public ResponseEntity<Void\> deleteBatch(@RequestParam List<Long\> ids) {
    service.deleteBatch(ids);
    return ResponseEntity.noContent().build();
}

6. HEAD(仅获取响应头,不获取 Body)
  • 前端 Fetch
fetch('/api/files/123', { method: 'HEAD' }).then(res \=> {
    console.log(res.headers.get('Content-Length')); // 获取文件大小
    console.log(res.headers.get('Last-Modified'));  // 获取修改时间
    // 注意:此时 res.body 为空,无法读取数据
});
  • 后端 Spring Boot
// 方式一:@GetMapping 默认自动支持 HEAD(但会执行完整查询逻辑,浪费性能)
// 方式二:专门写轻量级 HEAD 逻辑(推荐)
@RequestMapping(value = "/files/{id}", method = RequestMethod.HEAD)
public ResponseEntity<Void> head(@PathVariable Long id) {
    long size = service.getFileSize(id); // 只查元数据,不读文件流
    return ResponseEntity.ok()
            .header("Content-Length", String.valueOf(size))
            .build();
}

7. OPTIONS(预检/探测支持的方法)
  • 前端 Fetch(通常浏览器自动发,无需手动,但可测试)
fetch('/api/users', { method: 'OPTIONS' }).then(res \=> {
    console.log(res.headers.get('Allow')); // 打印服务器支持的方法,如 GET,POST,PUT,DELETE
});
  • 后端 Spring Boot无需编写任何代码

java

// Spring 框架自动响应 OPTIONS 请求。
// 只要在类上或方法上标注了 @CrossOrigin 或全局 CORS 配置,
// 框架会自动返回 Allow 头部和跨域相关头部。
// 如果完全没配 CORS,OPTIONS 也会返回默认支持的 Allow 头。

这是浏览器强制自动发出的,只有同时满足以下两个条件才会触发:

  • 条件一(跨域):前端页面域名(如 localhost:3000)和后端接口域名(如 api.example.com)不同。

  • 条件二(非简单请求):请求不满足“简单请求”标准。最常见的是:

    • 用了 PUTDELETEPATCH 方法。

    • 请求头带了 AuthorizationX-Token 等自定义头。

    • Content-Typeapplication/json
      注意:如果是跨域但满足“简单请求”(比如纯 GET 请求,且不带自定义头,只传 text/plain),浏览器不会OPTIONS,直接发 GET


8、 GET 与 POST 的区别

GET 和 POST 是最常用的两种方法,初学者容易混淆。核心差异如下:

对比维度GETPOST
语义获取/读取资源创建资源或提交数据
参数位置URL 查询字符串(Query String)请求体(Body)
是否有 Body否(规范上不携带 Body)是(JSON、表单等)
是否幂等是(重复请求不改变资源)否(重复提交可能创建多条记录)
是否可缓存通常可缓存通常不缓存
参数长度受 URL 长度限制(约 2KB~8KB,因浏览器/服务器而异)无严格限制,适合大数据量
可见性参数出现在 URL 中,会进入浏览器历史、服务器访问日志参数在 Body 中,不显示在地址栏
典型场景查询列表、搜索、分页、获取详情登录、注册、创建订单、提交表单、文件上传
如何选用:
  • 读数据、不改变服务器状态 → 用 GET(如 /api/products?category=phone
  • 写数据、创建或提交 → 用 POST(如 POST /api/orders 创建订单)
  • 敏感信息(密码、Token)→ 应放在 POST Body 中,不要放在 GET 的 URL 参数里

常见误区:「POST 比 GET 安全」并不绝对——POST 只是参数不出现在 URL 中;传输安全依赖 HTTPS。另外,部分老系统用 POST 做查询(参数放 Body),不符合 REST 语义,但技术上可行。

1.6 HTTP 状态码:场景举例

状态码是服务器告诉客户端「这次请求结果如何」的三位数字。先看第一位就能大致判断:

首位类别含义谁的问题?
1信息性收到,继续处理
2成功请求成功✅ 正常
3重定向需要去另一个地址通常正常
4客户端错误请求有问题❌ (前端/调用方)
5服务器错误服务端出错了❌ 后端/运维

遇频率说明(下文示例中标注):

标记含义
⭐⭐⭐日常开发必遇,几乎每个人都见过
⭐⭐做 API/上传/权限时会遇到
特定场景才出现,知道即可

5xx 服务器错误 ⭐⭐⭐

500 Internal Server Error

502 Bad Gateway

503 Service Unavailable

4xx 客户端错误 ⭐⭐⭐

400 Bad Request

401 Unauthorized

403 Forbidden

404 Not Found

409 Conflict

3xx 重定向 ⭐⭐

301 Moved Permanently

302 Found

304 Not Modified

2xx 成功 ⭐⭐⭐

200 OK

201 Created

204 No Content

1xx 信息性 ⭐

100 Continue

一眼速查(带举例)
状态码含义举例(你什么时候会看到)频率
200成功登录成功返回用户信息;查询订单列表⭐⭐⭐
201已创建POST 新建客户/订单,资源创建成功⭐⭐⭐
204成功,无内容DELETE 删除一条记录,不需要返回 body⭐⭐
301永久搬家旧域名 http://old.com 永久跳到 https://new.com⭐⭐
304用缓存刷新页面时,CSS 没改过,浏览器直接用本地缓存⭐⭐
400参数错了手机号少一位、JSON 少逗号、必填字段没传⭐⭐⭐
401没登录/Token 失效Token 过期调接口;没带 Authorization 头⭐⭐⭐
403没权限普通员工访问「仅管理员」接口⭐⭐⭐
404找不到URL 写错 /api/usres;订单 ID 不存在⭐⭐
500服务器崩了后端空指针、SQL 报错、未捕获异常⭐⭐⭐
502网关连不上后端Nginx 后面的 Java 服务挂了⭐⭐
503服务暂不可用系统维护中;流量太大被限流熔断⭐⭐
504请求超时504 Gateway Timeout,是后端服务(Tomcat/Node)处理请求太慢了,超过了中间层(如 Nginx)设置的等待时间⭐⭐⭐

下面按类别展开,每个状态码用真实场景 + 请求/响应示例说明,帮助理解「什么情况下会遇到」。


1xx 信息性响应(⭐ 很少直接感知)

这类状态码你在浏览器里几乎看不到,大文件上传、WebSocket 升级时才会涉及。

100 Continue ⭐

场景: 上传 500MB 文件前,客户端先问服务器「我准备发大 body 了,你要吗?」,服务器说「继续发」。

# 客户端先发请求头
PUT /api/files/big.zip HTTP/1.1
Expect: 100-continue

# 服务器同意
HTTP/1.1 100 Continue

# 客户端再发送文件内容...

你什么时候遇到: 自己写大文件上传客户端,或用 curl -L 上传超大文件时。日常调 JSON 接口基本不会见到。

101 Switching Protocols ⭐

场景: 网页从 HTTP 升级到 WebSocket 长连接(在线聊天、实时通知)。

GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade

你什么时候遇到: 做 WebSocket 开发时;普通 REST API 不会遇到。


2xx 成功(⭐⭐⭐ 最常见)
200 OK ⭐⭐⭐

场景 1: 查询用户列表成功

GET /api/users?page=1 HTTP/1.1
Authorization: Bearer eyJhbGci...

HTTP/1.1 200 OK
Content-Type: application/json

{"data": [{"id": 1, "name": "张三"}], "total": 100}

场景 2: 登录成功(也有接口用 200 而非 201)

POST /api/login HTTP/1.1
Content-Type: application/json

{"username": "admin", "password": "123456"}

HTTP/1.1 200 OK

{"token": "eyJhbG...", "userId": 1}

⚠️ 注意陷阱: 有些接口 HTTP 返回 200,但 body 里写 "code": 500, "message": "余额不足"。所以要同时看状态码和 body

// HTTP 200,但业务失败 —— 很多国内接口这样设计
{"code": 40001, "message": "订单不存在", "success": false}
201 Created ⭐⭐⭐

场景: 新建一条销售订单、创建一个客户

POST /api/sales-orders HTTP/1.1
Content-Type: application/json

{"customerId": 100, "items": [{"sku": "A001", "qty": 2}]}

HTTP/1.1 201 Created
Location: /api/sales-orders/9527
Content-Type: application/json

{"id": 9527, "status": "pending", "createdAt": "2026-07-06T10:00:00Z"}

和 200 的区别: 201 专用于「新资源被创建」,响应头里常有 Location 指向新资源地址。

204 No Content ⭐⭐

场景: 删除一条记录、更新设置(不需要返回任何数据)

DELETE /api/users/42 HTTP/1.1
Authorization: Bearer eyJhbG...

HTTP/1.1 204 No Content
(响应体为空)

前端常见坑:

// ❌ 204 没有 body,这样写会报错
const data = await response.json();  // Unexpected end of JSON input

// ✅ 正确写法
if (response.status === 204) {
  console.log('删除成功');
} else {
  const data = await response.json();
}
206 Partial Content ⭐

场景: 视频播放拖动进度条、断点续传下载

GET /videos/demo.mp4 HTTP/1.1
Range: bytes=0-1023

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/1048576
Content-Length: 1024

(只返回文件的第 0~1023 字节)

你什么时候遇到: 看视频拖进度条、下载工具「续传」时。调普通 JSON 接口不会遇到。


3xx 重定向(⭐⭐ 浏览器常见,API 调用需注意)
301 Moved Permanently ⭐⭐

场景: 公司换了域名,旧地址永久跳转到新地址

GET http://old-company.com/api/users HTTP/1.1

HTTP/1.1 301 Moved Permanently
Location: https://new-company.com/api/users

举例: 访问 http://example.com 被永久跳到 https://example.com(HTTP → HTTPS)。

你该怎么做: 更新代码里的 baseURL,不要长期依赖 301 跳转。

302 Found ⭐⭐

场景: 未登录访问后台,被临时跳到登录页

GET /admin/dashboard HTTP/1.1
Cookie: (无 session)

HTTP/1.1 302 Found
Location: /login?redirect=/admin/dashboard

和 301 的区别: 302 是临时跳转,以后还可能变回原地址。

⚠️ 经典坑: 旧浏览器遇到 302 时,可能把 POST 变成 GET,导致提交的数据丢失。现代 API 更推荐用 307/308

304 Not Modified ⭐⭐

场景: 浏览器第二次加载网页,问服务器「我本地的 app.js 改过吗?」,服务器说「没改,用你缓存的就行」

GET /static/app.js HTTP/1.1
If-None-Match: "abc123"
If-Modified-Since: Wed, 01 Jul 2026 10:00:00 GMT

HTTP/1.1 304 Not Modified
(无 body,浏览器直接用本地缓存)

你什么时候遇到: 打开 DevTools → Network,看到某些静态资源 Status 是 304。说明缓存生效,不是错误

开发排查: 「我明明改了代码,页面怎么还是旧的?」→ 强刷 Ctrl+F5 或禁用缓存。


4xx 客户端错误(⭐⭐⭐ 开发中最常排查)

4xx = 你的请求有问题,优先检查:URL、参数、Header、Token、权限。

400 Bad Request ⭐⭐⭐

场景 1: JSON 格式错误

POST /api/users HTTP/1.1
Content-Type: application/json

{"name": "张三", "age": }    ← 少了值,JSON 非法

HTTP/1.1 400 Bad Request

{"error": "Invalid JSON at line 1 column 25"}

场景 2: 必填参数缺失

POST /api/users HTTP/1.1

{"name": "张三"}    ← 缺少必填字段 email

HTTP/1.1 400 Bad Request

{"error": "Validation failed", "fields": {"email": "不能为空"}}

场景 3: 类型不对

POST /api/users HTTP/1.1

{"name": "张三", "age": "二十五"}    ← age 应该是数字

HTTP/1.1 400 Bad Request

{"error": "age must be a number"}

怎么排查: 对照 API 文档;用 Postman 对比正确请求;看响应 body 里的字段级错误。

401 Unauthorized ⭐⭐⭐

场景 1: 没带 Token

GET /api/orders HTTP/1.1
(没有 Authorization 头)

HTTP/1.1 401 Unauthorized

{"error": "Missing authentication token"}

场景 2: Token 过期

GET /api/orders HTTP/1.1
Authorization: Bearer eyJhbGci...(已过期)

HTTP/1.1 401 Unauthorized

{"error": "Token expired", "code": "TOKEN_EXPIRED"}

场景 3: 登录账号密码错误(有些接口也返回 401)

POST /api/login HTTP/1.1

{"username": "admin", "password": "wrong"}

HTTP/1.1 401 Unauthorized

{"error": "Invalid username or password"}

怎么排查: 检查 Authorization 头格式是否为 Bearer <token>;Token 是否过期;是否需要先调登录接口。

403 Forbidden ⭐⭐⭐

场景: 已登录,但没有权限操作

DELETE /api/admin/users/1 HTTP/1.1
Authorization: Bearer eyJhbGci...(普通员工 Token)

HTTP/1.1 403 Forbidden

{"error": "Permission denied", "required": "admin"}

和 401 的区别(必记):

状态码含义生活比喻
401不知道你是谁没刷工牌就进公司
403知道你是谁,但不让你做刷了工牌,但你是访客不能进机房
404 Not Found ⭐⭐⭐

场景 1: URL 路径写错

GET /api/usres/1 HTTP/1.1          ← users 拼成了 usres

HTTP/1.1 404 Not Found

{"error": "Route not found"}

场景 2: 资源已被删除或 ID 不存在

GET /api/orders/999999 HTTP/1.1

HTTP/1.1 404 Not Found

{"error": "Order 999999 not found"}

怎么排查: 核对 URL 拼写、HTTP 方法、资源 ID 是否存在。

405 Method Not Allowed ⭐⭐

场景: 对接口用了错误的 HTTP 方法

GET /api/users HTTP/1.1     ← 创建用户应该用 POST

HTTP/1.1 405 Method Not Allowed
Allow: POST

{"error": "Method GET not allowed, use POST"}

怎么排查: 看响应头 Allow 字段,确认支持的 Method。

408 Request Timeout ⭐

场景: 客户端发送请求体太慢,服务器等不及了

你什么时候遇到: 网络极差时上传大文件;物联网弱网环境。一般后端框架较少主动返回 408。

409 Conflict ⭐⭐

场景 1: 重复创建(邮箱/用户名唯一)

POST /api/users HTTP/1.1

{"email": "zhangsan@example.com"}    ← 该邮箱已存在

HTTP/1.1 409 Conflict

{"error": "Email already exists"}

场景 2: 乐观锁版本冲突(两人同时编辑)

PUT /api/orders/9527 HTTP/1.1

{"status": "shipped", "version": 3}    ← 服务器已是 version 4

HTTP/1.1 409 Conflict

{"error": "Resource was modified by another user", "currentVersion": 4}

场景 3: 重复提交订单(没做幂等)

POST /api/orders HTTP/1.1
Idempotency-Key: order-20260706-001    ← 同一 Key 提交了两次

HTTP/1.1 409 Conflict

{"error": "Duplicate request"}
413 Payload Too Large ⭐⭐

场景: 上传的文件超过服务器限制

POST /api/upload HTTP/1.1
Content-Type: multipart/form-data

(上传 200MB 文件,服务器限制 50MB)

HTTP/1.1 413 Payload Too Large

{"error": "File size exceeds 50MB limit"}

怎么解决: 压缩文件;分片上传;让运维调大 Nginx client_max_body_size

415 Unsupported Media Type ⭐⭐

场景: Content-Type 和服务端期望的不一致

POST /api/users HTTP/1.1
Content-Type: text/plain          ← 服务端只接受 JSON

{"name": "张三"}

HTTP/1.1 415 Unsupported Media Type

{"error": "Content-Type must be application/json"}

常见原因: 发了 JSON 但 Header 写成了 application/x-www-form-urlencoded

422 Unprocessable Entity ⭐⭐

场景: JSON 格式正确,但业务规则不满足

POST /api/orders HTTP/1.1

{"productId": 1, "quantity": -5}    ← 数量不能为负数

HTTP/1.1 422 Unprocessable Entity

{"error": "Validation failed", "fields": {"quantity": "must be greater than 0"}}

和 400 的区别: 400 偏「格式/语法错误」;422 偏「格式对,但语义/业务规则不通过」。很多框架两者混用,知道即可。

429 Too Many Requests ⭐⭐

场景: 接口被限流(防刷、API 配额)

GET /api/data HTTP/1.1

HTTP/1.1 429 Too Many Requests
Retry-After: 60

{"error": "Rate limit exceeded, max 100 requests per minute"}

举例: 1 分钟内调了 200 次接口;短信验证码连点 5 次;爬虫被抓。

怎么解决:Retry-After 秒数后重试;加缓存;降低调用频率。


5xx 服务器错误(⭐⭐⭐ 需要后端/运维排查)

5xx = 服务端的问题,前端通常无法自行修复,应记录请求信息并联系后端。

500 Internal Server Error ⭐⭐⭐

场景 1: 后端代码 bug(空指针)

GET /api/orders/9527 HTTP/1.1

HTTP/1.1 500 Internal Server Error

{"error": "Internal server error"}    ← 生产环境通常不暴露细节

场景 2: 数据库连接失败

后端日志:Connection refused: mysql://localhost:3306
前端看到:500 Internal Server Error

场景 3: 未捕获的异常

# 后端代码
name = order.customer.name   # customer 是 null → 500
502 Bad Gateway ⭐⭐

场景: Nginx/网关前面的服务正常,但后面的应用挂了

用户 → Nginx(正常)→ Java 应用(进程挂了)→ 502
GET /api/users HTTP/1.1

HTTP/1.1 502 Bad Gateway

<html><body>502 Bad Gateway</body></html>

常见原因: 后端进程崩溃;Docker 容器重启中;upstream 地址配错;端口不通。

和 500 的区别: 500 是应用自己报错;502 是网关连不上应用

503 Service Unavailable ⭐⭐

场景 1: 系统维护

GET /api/users HTTP/1.1

HTTP/1.1 503 Service Unavailable
Retry-After: 3600

{"error": "System maintenance, back at 18:00"}

场景 2: 过载/熔断

流量突增 → 服务器扛不住 → 主动返回 503 保护系统

你怎么应对:Retry-After 头;稍后重试;联系运维确认是否在维护。

504 Gateway Timeout ⭐⭐

场景: 后端处理太慢,网关等超时了

POST /api/reports/generate HTTP/1.1    ← 生成报表要 5 分钟

HTTP/1.1 504 Gateway Timeout

{"error": "Gateway timeout after 60s"}

常见原因: 慢 SQL;导出大数据;第三方 API 响应慢;Nginx proxy_read_timeout 太短。

怎么解决: 优化后端性能;改为异步任务(先返回 202,完成后通知);调大网关超时。

507 Insufficient Storage ⭐

场景: 服务器磁盘满了,无法写入

你什么时候遇到: 自建服务器、网盘类应用。云 SaaS 较少直接暴露 507。


在 Chrome DevTools 里看状态码
  1. F12 打开开发者工具
  2. 切到 Network(网络) 标签
  3. 刷新页面或触发请求
  4. Status 列:200 绿色、3xx/4xx/5xx 通常橙色或红色
Name              Status   Type
users             200      xhr        ← 成功
login             401      xhr        ← Token 失效,要重新登录
orders/999        404      xhr        ← 订单不存在
upload            413      xhr        ← 文件太大
api/data          502      xhr        ← 后端挂了,找运维

1.7 HTTP vs HTTPS

特性HTTPHTTPS
端口80443
加密明文传输TLS/SSL 加密
证书不需要需要 CA 证书
安全性低(可被窃听/篡改)
性能无 TLS 握手开销首次连接需 TLS 握手(约 1~2 RTT)

HTTPS(超文本传输安全协议) 就是 HTTP 的安全加强版。简单说,它等于 HTTP + SSL/TLS 加密层

它的核心价值在于解决了 HTTP 最致命的缺陷——明文传输。在 HTTP 下,你的账号密码、聊天记录在网络中像“裸奔”一样能被任何人窃取或篡改,而 HTTPS 通过加密手段,将这些信息装进了一个只有收发双方才能打开的“保险箱”里。

具体来说,HTTPS 做了三件关键的事:

  1. 数据加密(防窃听):将传输内容打乱成乱码,即使黑客截获了数据包,看到的也是一堆无意义的密文。

  2. 数据完整性(防篡改):确保数据在传输过程中没有被中间人偷偷修改或调包。

  3. 身份验证(防冒充):通过数字证书验证服务器确实是它声称的那个网站(比如你访问银行网站,证书能证明它真的是银行,而不是钓鱼网站)。

为了实现这些,HTTPS 采用了混合加密策略:握手阶段使用非对称加密(公钥/私钥)安全地交换密钥;数据传输阶段则改用对称加密,这种算法计算量小、速度快,保证了用户体验。

HTTPS(加密)

HTTP

TLS 加密层

TCP

HTTP(明文)

HTTP

TCP

日期:2026-07-10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值