「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」
上次,有个新来的同事和我调接口。就是一个普通的请求具体信息的接口,传个id就完事了。 我熟练地用问号拼接了参数,并发起了请求。结果,居然报错了,说我没有传id过去?
我眉头一皱,事情并不简单。先看看我的请求,嗯,没啥问题, 再看看她的接口怎么写的。 咦? 这个参数似乎是放在body里的,仔细看了看了method,的确是GET没有错。难道get还能携带body不成,我且试试。 不行,ts语法校验过不去。 要不把校验关了? 算了,这个get函数的实现就是这样,放个body进去它也是无感知的,会被解析转换为问号参数。还是直接甩锅。
于是我理直气壮的找到了写接口的人。 嘿,你不知道get请求不能携带body吗? 她茫然的看着我,说我用postman测试的时候,是可以的啊。 真是像极了那句 it works on my machine。 但是我是来甩锅的,怎么可能被这种,我用惯了的话挡回去。 我正告她, 你在浏览器上试过没有, 浏览器上的请求实现和postman的是一样吗(张口就来,貌似我说的还有点道理)? 她转头求助于带她的同事,另一位同事也直接告诉她,以后不要在get请求里使用body了。 但是,这位同事还挺好学的,她想知道为什么。 我也想知道啊,我说待我去翻翻书,书到用时方恨少啊。
所以问题来了。
get请求能携带body吗? 与之对应我又想到了另外一个问题, post请求不能缓存吗?
要回答这两个问题,就要搞清楚get和post的区别,以及稍微深入一点的原因。毕竟,http可不是天造的。
一般的区别
下面的表格比较了两种 HTTP 方法:GET 和 POST。
| GET | POST | |
|---|---|---|
| 后退/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
| 书签 | 可收藏为书签 | 不可收藏为书签 |
| 缓存 | 能被缓存 | 不能缓存 |
| 编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded or multipart/form-data。为二进制数据使用多重编码。 |
| 历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
| 对数据长度的限制 | 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
| 对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
| 安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。 在发送密码或其他敏感信息时绝不要使用 GET ! | POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
| 可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中。 |
http
但是请注意,上面的区别是直接告诉我们的,而且是在浏览器中(一般可不就在浏览器吗)。所以,她用postman直接发请求的时候做到了浏览器上做不到的事。 由此可见,这个http的实现似乎并不固定啊。
我们知道,http协议是TCP/ip协议的一个子类, 或者说是TCP/ip 派生出来的。http的全称是HyperText Transfer Protocol超文本传输协议,用于客户端到服务端的通信。 我们暂时不用去深入了解TCP/ip,只用看http即可。
服务端和客户端
能发送请求并接收响应信息的就是客户端(我们前端), 能接收并响应请求的就是服务端(后端)。
从上面的粗略定义可以看出, 一台机器可以既是服务端又是客户端(实际上,们前端本地启动就是这样的)。
但是,在一次http通信中,服务端和客户端是确定了的。一个请求必然是客户端发起,服务端响应。
看到这里好像和get post没啥关系啊。不急,马上就到重点了。
http协议是用于两端之间的通信的,但是这样的请求没有什么规律,为了语义化一些,于是有了请求方法, 实际上也就是请求类型。 get 和 post 。 get用于访问已被URI识别的请求, post则用于请求进行一些操作。
不过,协议这东西需要大家一起遵守才行。 就比如说get请求,后端在监听到了get请求之后,也可以进行数据修改,但是这不合规矩,不讲网德,是吧。因为get,期望是只访问,而不进行其他操作,下一次我再发相同的请求,你就照旧就行了。 post请求,就刚好相反,期望是一个指令,去做点什么,我要做什么事,那肯定是不留痕迹,要干干净净的。
缓存
回到最初的问题。get能不能带body啊, 能是能,但是浏览器实现会忽视掉get的body,也就是浏览器中get不能把body带给服务端。
然后,说一下为什么get被设计成这样,借用某位大佬的观点,因为缓存是用get的url作为键的,你的body如何变化都不会影响到它,也就是说body没用。
反过来,因为post常常涉及到修改资源的操作,所以缓存是没有意义的,请求一次就有可能变一次,还缓存什么。