【前端面试小册】网络-第5节:GET 与 POST 进阶
一、概述
1.1 最大区别
GET 和 POST 方法最大区别:
- 报文格式不同
- 语义不同:GET 获取资源,POST 向服务端提交资源
类比理解:
- GET:就像去图书馆借书,你告诉图书管理员书名(参数在 URL 中),管理员把书给你
- POST:就像往银行存钱,你把钱(数据在 body 中)交给柜员
二、RFC 角度的区别
2.1 RFC 是什么
RFC:Request For Comments,超文本传输协议(Hypertext Transfer Protocol)的标准规范。
2.2 RFC 标准中的区别
| 特性 | GET | POST |
|---|---|---|
| 用途 | 获取信息 | 修改服务器上的数据 |
| 副作用 | 无副作用 | 有副作用 |
| 幂等性 | 幂等 | 非幂等 |
| 缓存 | 可缓存 | 不可缓存 |
幂等:任意多次执行所产生的影响均与一次执行的影响相同。
示例:
- 幂等:GET
/users/1多次执行,返回相同结果 - 非幂等:POST
/users多次执行,创建多个用户
2.3 为什么会有这些区别
因为大部分浏览器实现了 RFC 标准,所以上面的一些区别是存在的。
三、报文角度的区别
3.1 核心观点
从报文角度来看:GET 和 POST 都只是 HTTP 协议中的请求方式,而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。
3.2 不带参数时 GET 和 POST 区别
GET 请求
GET /uri HTTP/1.1\r\n
Host: localhost
POST 请求
POST /uri HTTP/1.1\r\n
Host: localhost
结论:不带参数时,二者仅仅只有报文的前几个字符不同而已。
3.3 带参数时 GET 与 POST 区别
GET 请求
GET /index?age=1 HTTP/1.1
Host: localhost
特点:
- 参数在 URL 中
- 通过
?连接 - 多个参数用
&分隔
POST 请求
POST /index HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
age=1
特点:
- 参数在 body 中
- 需要指定 Content-Type
- 数据在请求体中
3.4 本质
而这两种方法的本质就是 TCP 连接,没有差别。
如果我们不按照规范来:
- 可以使用 POST 的时候在 URL 带上参数
- 使用 GET 的时候,在 body 写上参数,只要服务端支持即可
示例:
POST /index?age=1 HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
name=test
四、常见误区
4.1 参数写法固定?
正常写法
http://www.demo.com/info?age=1&name=2
非正常写法
http://www.demo.com/info@age=1%name=2
结论:非正常写法,只要后端支持就可以了。URL 的参数分隔符只是约定俗成的规范。
4.2 POST 比 GET 更安全?
错误观点:POST 比 GET 更安全。
真相:HTTP 中 GET 和 POST 都是明文传输,只要在网络节点上被人拦截,就可以获取到数据报文。
解决方案:想要安全还是得加密,走 HTTPS。
对比:
| 传输方式 | 安全性 | 说明 |
|---|---|---|
| HTTP GET | 不安全 | 明文传输 |
| HTTP POST | 不安全 | 明文传输 |
| HTTPS GET | 安全 | 加密传输 |
| HTTPS POST | 安全 | 加密传输 |
4.3 GET 长度限制 2048 字节?
误区:GET 请求的 URL 长度限制为 2048 字节。
真相:
- HTTP 协议没有对 Body 和 URL 长度限制!!!
- 对 URL 限制的是浏览器和服务器的原因
限制原因
-
超长 URL 会影响搜索引擎的爬虫
- 有些爬虫无法处理超过 2000 个字节的 URL
-
内存分配问题
- 在解析 URL 时要分配内存
- 且它只能当作整体看待,无法一块块处理
- 如果 URL 太长,而并发又很高,就容易挤爆服务器的内存
实际测试
自己起个 Node 服务,然后用 Postman 发一个请求,设置 URL 长度超过 2048 个字符,Node 服务是可以接收到的。
各浏览器限制对比
| 浏览器 | URL 最大长度 |
|---|---|
| Chrome | 2MB |
| Firefox | 65,536 字符 |
| Safari | 80,000 字符 |
| IE | 2048 字符(最严格) |
4.4 POST 会产生两个 TCP 数据包?
误区:POST 请求会产生两个 TCP 数据包。
真相:
- HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包
- 而且实际测试(Chrome)发现,header 和 body 不会分开发送
结论:
- header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 POST 必然行为
- POST 请求通常比 GET 请求大,所以 header 和 body 会分开发
- 要是 POST 请求足够小的话也不用发两个数据包
4.5 为什么 POST 不能添加为收藏?
误区:POST 不能添加为收藏。
真相:
- 首先 HTTP POST 都可以被收藏
- 但由于书签仅包括 URL,如果用 POST 所有的表单参数都将丢失
- 没有参数,Web 服务器不知道该如何处理请求,应该返回什么样的数据
对比:
- GET 请求:表单参数都在 URL 中,书签包含所有信息
- POST 请求:表单参数在 body 中,书签无法保存这些参数
五、实际应用场景
5.1 GET 使用场景
// 获取用户列表
fetch('/api/users?page=1&limit=10')
.then(res => res.json())
.then(data => console.log(data));
// 搜索
fetch('/api/search?keyword=javascript')
.then(res => res.json())
.then(data => console.log(data));
// 获取用户详情
fetch('/api/users/123')
.then(res => res.json())
.then(data => console.log(data));
特点:
- 获取数据
- 参数简单
- 可缓存
- 可收藏
5.2 POST 使用场景
// 创建用户
fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '愚公上岸说',
email: 'test@example.com'
})
}).then(res => res.json())
.then(data => console.log(data));
// 上传文件
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('/api/upload', {
method: 'POST',
body: formData
}).then(res => res.json())
.then(data => console.log(data));
// 登录
fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'user',
password: 'pass123'
})
}).then(res => res.json())
.then(data => console.log(data));
特点:
- 提交数据
- 数据量大
- 修改服务器数据
- 不可缓存
六、最佳实践
6.1 RESTful API 设计
// 获取用户列表
GET /api/users
// 获取单个用户
GET /api/users/123
// 创建用户
POST /api/users
// 更新用户
PUT /api/users/123
// 删除用户
DELETE /api/users/123
6.2 参数传递建议
GET 请求
// ✅ 推荐
GET /api/users?page=1&limit=10&sort=name
// ❌ 不推荐
GET /api/users
Body: { page: 1, limit: 10 }
POST 请求
// ✅ 推荐
POST /api/users
Content-Type: application/json
Body: { "name": "test", "email": "test@example.com" }
// ❌ 不推荐
POST /api/users?name=test&email=test@example.com
七、面试要点总结
核心知识点
- 本质区别:报文格式和语义不同
- RFC 标准:GET 无副作用、幂等、可缓存;POST 有副作用、非幂等、不可缓存
- 传输层面:都基于 TCP,没有本质区别
- 常见误区:安全性、长度限制、TCP 数据包
常见面试题
Q1: GET 和 POST 的区别?
答:
- 语义不同:GET 获取资源,POST 提交资源
- 参数位置:GET 参数在 URL,POST 参数在 body
- 幂等性:GET 幂等,POST 非幂等
- 缓存:GET 可缓存,POST 不可缓存
- 安全性:都是明文传输,需要 HTTPS 保证安全
Q2: GET 请求的 URL 长度有限制吗?
答:HTTP 协议本身没有限制,限制来自浏览器和服务器。不同浏览器限制不同,IE 最严格(2048 字符)。
Q3: POST 比 GET 更安全吗?
答:不是。在 HTTP 中,GET 和 POST 都是明文传输,都不安全。要安全需要使用 HTTPS。
实战建议
- ✅ 根据语义选择合适的方法
- ✅ GET 用于获取数据,POST 用于提交数据
- ✅ 重要数据传输使用 HTTPS
- ✅ 遵循 RESTful API 设计规范
