背景
Get和Post都是HTTP协议中的请求方法,用于向服务器发送请求。
本质都是TCP的请求,浏览器可以发,其他应用程序也可以发。
说区别的时候,需要区分场景的,比如浏览器端有什么区别,中间转发服务层又有什么区别?
浏览器端的视角
在请求的发送和接收过程中,是经过浏览器处理的,所有很多区别都是浏览器的行为。
- 语义化:这个是规范定义的,GET请求是用来获取资源的,POST请求是用来提交数据的。
- 幂等性:GET请求是幂等的,POST请求是非幂等的。由于语义化的不同,衍生出了幂等性的差异
- 缓存:GET请求会被浏览器自动缓存,POST请求不会被浏览器自动缓存。
- 浏览器添加的限制,是为了让请求更加高效,因为幂等性 所以GET请求是可以被缓存的,这样也能减少不必要的请求。
- 可以通过cache-control: no-cache来禁用自动缓存
- 数据长度:GET请求的数据长度是有限制的,POST请求的数据长度是没有限制的。
- 浏览器添加的限制,主要是服务端处理时超长字符串是不能分割的,所以需要限制数据长度。
- 参数传递:GET请求的参数是放在URL中的,POST请求的参数是放在请求体中的。
- 规范定义的,但是实际实现可以是在URL中,也可以是在请求体中。
中间转发层的视角
中间转发层是指浏览器和服务器之间的中间层,比如代理服务器、网关服务器、负载均衡服务器等。
对于转发层而言,GET和POST请求没有本质区别,都是TCP的请求。主要区别就是语义化。
预检请求
是什么?为什么?
对于一些复杂请求来说,请求发送之前有一个OPTIONS请求,这个请求叫做预检请求。
预检请求是为了检查服务器是否支持该请求,比如是否支持跨域请求,是否支持该方法,是否支持该请求头等。
复杂请求
复杂请求对应的就是简单请求:
- 请求方法是
GET、HEAD、POST - 请求头是
Accept、Accept-Language、Content-Language、Content-Type - 请求头是
Content-Type的值是application/x-www-form-urlencoded、multipart/form-data、text/plain - 请求头是
Content-Type的值是application/json,但是请求头是Content-Length的值是0
简单记忆:复杂请求就是有自定义头部字段、额外的Content-Type字段等等
为什么需要预检请求?
讨论为什么,就是在讨论没有预检请求会怎么样。
如果没有预检请求,请求直接发送,服务端会先接收请求头,解析请求头的控制信息,然后判断是否需要接收请求体内容。 这样就麻烦一些,而且还可能导致不必要的网络传输流量;另外直接和服务端交互,可能会导致报错信息不一致。
如果有预检请求在中间的话,就可以先发送预检请求,服务端收到预检请求后,会先判断是否支持该请求,如果支持,就会发送一个200响应,然后再发送真实请求;如果不支持,忽略服务端的响应,报错信息统一。
这样就可以避免不必要的网络传输流量,也可以避免服务端的错误。
另外预检请求还能设置缓存,比如服务端设置响应头Accecc-Control-Max-Age: 60,表示预检请求的结果缓存60秒,这样就可以避免重复的预检请求。
总结
说区别的时候,需要区分使用场景。另外规范是人定的,只要上下游确定好之后,更加符合业务,也不一定就要死套规范。