【计算机网络】HTTP 协议-1:https://developer.aliyun.com/article/1430646
针对 GET 方法和 POST 方法的区别的一些错误看法
1. GET 请求能传递的数据有上限,POST 传递的数量没有上限。
这个说法其实是一个“历史遗留”,早期版本的浏览器,因为硬件资源特别匮乏,所以浏览器就对 URL 的长度进行了限制,因为 GET 方法通常是将传输给服务器的数据加在 URL 的 query string 中,所以当用 GET 方法要传给服务器的数据较多的时候就会导致 URL 会很长。
但是实际上,RFC 标准文档 并没有明确规定 URL 能有多长,而且现在由于技术的进步,URL 也可以很长,甚至可以用 URL 来传递一些图片等。所以这个说法是错误的。
2. GET 请求传递数据不安全,POST 请求传递数据更安全。
为什么会这样说呢?因为在使用 GET 请求登录的时候,会将用户名和密码放入 URL 中,进一步显示在浏览器的地址栏当中,这样别人不就能轻易看到了吗?而 POST 更安全就说的是因为 POST 会将用户名和密码放入 body 中,这样就不会显示在浏览器搜索栏中,那么此时就是安全的了。但是这个说法是错误的,这个说法只能忽悠小白。什么叫做安全?安全就只是不将用户名和密码显示在搜索栏中吗?那可不是,所谓安全就是这个请求包不会被轻易的被黑客给截取到,就算被截取到了黑客也需要花出大于该数据本身的价值来破解这个数据包。不管是 GET 请求的数据包还是 POST 数据的数据包,当数据包被截取到了,知道这个请求数据包的首行和正文(body)部分都是轻而易举的。
所以为了解决这个传输数据的过程中被黑客截取到然后可以直接知道你数据的内容的问题,就采取了对用户名和密码进行加密的措施,这样就算你获取到了这个请求数据包,因为用户名和密码是经过加密的,黑客是不容易破解的。
3. GET 只能给服务器传输文本数据,POST 可以给服务器传输文本和二进制数据。
请求数据包的正文(body)部分可以放文本数据也可以放二进制数据,为什么会有这个说法呢?其实这个说法还是基于第一个说法的,就是因为被误以为 GET 方法传输给服务器的数据只能写入 URL 的 query string 中,而 URL 中的数据往往是文本数据,但是 GET 方法传输给服务器的数据是可以写入 正文(body)部分的,所以 GET 方法也是可以传输二进制数据的。
GET 方法和 POST 方法的区别的说法有一定的道理但不严谨的说法
1. GET 方法是幂等的,POST 方法是非幂等的。
什么是幂等和非幂等呢?
幂等是指同一个系统,同样的参数条件,一次请求和多次同样重复的请求对资源的影响一样。例如,一次插入请求插入一条数据,多次插入请求产生的影响也是多一条数据,那么就是幂等的。
非幂等是指同一个系统,同样的参数条件,一次请求和多次同样重复的请求对资源的影响不一样。例如,用户重复操作,如用户提交请求进行创建订单操作,由于网络问题,导致页面一直在转,用户重新点击创建订单按钮,就会产生同样的订单在数据库中创建了两条,这就是非幂等的。
为什么说 GET 方法是幂等的,POST 方法是非幂等的呢?因为在 RFC 标准文档中有这样一个建议:建议 GET 请求的数据是幂等的。但是这只是一个建议,并不是硬性要求,所以这个说法不严谨。
2. GET请求可以被浏览器缓存,POST 方法不可以被浏览器缓存。
这个说法虽然有一定的正确性,但并不严谨。这是因为GET和POST请求本身都可以被缓存,只是浏览器在处理这两种请求时的行为和机制有所不同。
对于GET请求,浏览器会缓存GET请求的响应结果,以便在后续相同的请求时直接使用缓存的响应,而不需要再次向服务器发送请求。这是由于GET请求是幂等的,即多次发送相同的GET请求将获得相同的结果,不会对资源产生任何额外的影响。
然而,对于POST请求,浏览器通常不会缓存响应结果。这是因为在大多数情况下,POST请求用于提交数据或执行更新操作,每次请求的结果可能会有所不同。浏览器为了确保每次POST请求都会向服务器发送最新的数据和产生最新的结果,不会缓存POST请求的响应结果。
然而,这并不意味着POST请求绝对不会被缓存。实际上,一些浏览器或代理服务器可能会对POST请求进行缓存,特别是在某些情况下,例如当使用缓存代理时。此外,一些Web应用程序也可能通过编程方式实现POST请求的缓存。
因此,这个说法“GET请求可以被浏览器缓存,POST 方法不可以被浏览器缓存”虽然在一定程度上反映了浏览器对GET和POST请求的处理机制,但并不适用于所有情况。在具体的上下文中,需要考虑浏览器的行为、Web应用程序的实现以及其他因素来评估这个说法的准确性。
3. GET 请求可以被浏览器收藏,POST 请求的数据不能被收藏。
这个说法也是不严谨的。实际上,GET请求和POST请求都可以被浏览器收藏,但它们在收藏过程中有一些区别。
对于GET请求,浏览器会将请求的URL和参数一起保存下来,以便用户可以在以后直接点击该URL来重新加载页面或获取数据。这种方式很常见,例如在浏览器书签中保存网页URL。当用户点击该URL时,浏览器会发送一个GET请求到服务器,然后服务器会返回相应的网页内容。因此,GET请求可以被浏览器收藏。
对于POST请求,浏览器不会直接保存请求的URL和参数,因为POST请求是向服务器发送数据的请求方式。浏览器将POST请求的数据包含在请求体中,而不是URL中。但是,用户可以在浏览器中手动复制和粘贴POST请求的URL和参数,或者使用开发者工具来查看和复制POST请求的内容。因此,虽然浏览器不会自动收藏POST请求的数据,但用户仍然可以手动将其保存下来。
需要注意的是,浏览器收藏的GET请求URL可能包含敏感信息,例如身份验证令牌或密码等。为了保护用户的隐私和安全,这些信息应该通过POST请求或其他安全机制发送到服务器。
Header
Header 中的键值对是有很多的,但是这里我们主要挑选几个来介绍。
Host
Host:表示服务器主机的地址和端口。这里的内容通常在 URL 中也有体现,但是如果使用代理的情况下 Host 的内容和 URL 中的内容可能就不一样了。
Content-length
Content-length:表示 body 中的数据长度。
Content-length 有什么用,因为 HTTP 是基于 TCP 的,TCP 在传输的过程中可能会出现粘包的问题,如果使用同一个 TCP 连接传输多个 HTTP 数据包的时候,这样多个 HTTP 数据包就会在接收缓冲区当中挨着等待,接收方在接收这些 HTTP 数据包的时候就需要清楚 HTTP 数据包的边界,对于 GET 这种一般没有 body 部分的数据包就需要使用 空行 来作为分隔符;而对于 POST 来说,一般是有 body 部分的,所以就需要通过 空行和 Content-length 来区分不同的数据包。
只有请求中有 body 部分的时候,才会有 Content-length 和 Content-type 这两个键值对。
Content-type
Content-type:表示 body 中数据的格式。
body 中数据格式的种类是有很多的:
请求:
- JSON
- form 表单格式
- form-data 的格式
这种数据格式就是一种 json 数据格式。
当 Content-type 是以下这种形式的时候就表示是 form 表单格式。
form 表单就相当于把 GET 的 query string 给搬到 body 中。
而 form-data 格式通常是在上传文件的时候会涉及到,但上传文件的时候也不一定都是 form-data 格式,也可能是 form 表单格式。
响应:
- HTML
- CSS
- JS
- JSON
- 图片
通常在 Fiddler 中抓取到的蓝色的就属于是 HTML 格式的数据包;紫色就是 CSS、绿色是 JavaScript、黑色是 JSON。
HTML CSS JS 用来构成网页的主体。
- HTML 表示页面的骨架(页面上有啥东西)
- CSS 表示页面的样式(页面长啥样)
- JavaScript 表示页面的行为
交给服务器的 Content-type 不同,服务器的处理数据逻辑也是不同的,服务器返回处理的数据的时候也需要表明 Content-type,浏览器也会根据不同的 Content-type 做出不同的处理。
User-Agent(简称 UA )
通过上面的抓包,观察 User-Agent 我们可以看到几个很常见的消息:Windows NT 10.0;win64;x64 这表示的是我们使用的主机的相关信息,而 Chrome/118.0.0.0 则表示的是我们使用的浏览器的版本号。通过这两个信息我们大概可以知道 User-Agent 表示的就是与当前浏览器相关的信息。
为什么 HTTP 数据包中会出现这个 UA 呢?其实在很早之前,那时候浏览器刚刚发展,最开始浏览器网页就只是单纯的文字,并没有什么图片,并且浏览器的相关功能也很简单,但是随着浏览器的发展,浏览器上开始能显示图片以及一些声音信息了,那么有些人就会选择更新浏览器版本,但是在新浏览器普及的过程中,普及的过程是缓慢的,所以就会出现旧浏览器和新浏览器并存的情况,那么当用户访问的时候,服务器应该返回有图片的网页还是无图片的网页呢?如果返回有图片的数据,那么就浏览器就不支持这个功能,但是如果返回一个没有图片的网页,那么新版本浏览器更新又有什么用呢?所以这时候 UA 就发挥作用了,服务器可以根据请求中 UA 反应的浏览器版本来返回不同的网页。
但是现在其实 UA 就没那么关键了。因为现在不同版本的浏览器功能几乎是差不多的,现在的 UA 主要是用来辨别你是 PC 端还是移动端的,虽然可以用来辨别是 PC 端还是移动端,但是返回的网页其实跟这个 UA 无关。这个 UA 是用来统计数据的。现在的前端开发,有“响应式网页”编程的技术,同一个 HTML 可以兼容不同的设备。
Referer
Referer 描述了当前网页面是从哪个页面跳转过来的。直接在搜索栏中输入 URL 是没有 Referer 的。
Referer是HTTP请求中的header部分,当浏览器向web服务器发送请求时,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
Referer主要有两个作用:
- 防盗链:只允许我本身的网站访问本身的图片服务器,假如域名是www.google.com,那么图片服务器每次取到Referer来判断一下域名是不是www.google.com,如果是就继续访问,不是就拦截。
- 防止恶意请求:对于某些风险较高的文件类型,可使用Referer使得该类型文件只能来自我所指定的网站。
很多搜索引擎中的广告都是需要广告商给搜索引擎这个公司出广告费的,有的广告费就是根据这个广告挂在搜索引擎多长时间计费的,而大多数广告费则是根据这个点击次数来计费的。那么搜索引擎或者广告商是如何判断某个点击是从哪个网站点击的呢?这里就需要用到 HTTP 数据包中的 Referer 了,通过 HTTP 数据包中的 Referer 就可以知道这个点击来自哪个页面。
但是是否会出现一个现象:这个 HTTP 数据包中的 Referer 会被恶意修改,修改成其他公司,从而导致最终的广告费都给了它们呢?其实是有可能的。在很早之前,因为进行网络数据的传输就需要经过网络运行商的交换机/路由器,那么这些网络运行商就可以将经过它们交换机/路由器的数据中的 Referer 进行修改,从而是他们最终成为受益者,并且这个现象在当时是非常猖獗的,因为当时互联网刚发展,相关的法律还没有完善,所以这些搜索引擎公司并不能拿这些网络运营商什么办法。所以这些搜索引擎就决定在技术上进行修改,对这些HTTP 数据包进行加密,这样网络运营商就不能轻易修改其中的 Referer 了。
Cookie
HTTP的cookie是服务器发送到用户浏览器并保存在本地的一小块数据,通常由服务器使用HTTP响应头Set-Cookie发送到浏览器。当浏览器再次向同一服务器发起请求时,会默认携带这些 Cookie,并发送到服务器上。
类似于一些信息:上次登录时间、上次访问时间、用户身份信息、累计访问次数等这些信息都会存储在浏览器的 Cookie 中,并且在下一次访问这个网站的时候会将这个 Cookie 一起发送过去。
因为这些数据都是临时的,随时都可能会改变,所以这些数据还是存在浏览器最合适,其实更容易想到的是将这些数据保存在我们的本地文件中,但是这样是不行的,为了保证安全性,浏览器会禁止网站直接访问你本地的文件,所以也就导致网页代码无法直接生成一个硬盘文件来存储数据了。所以为了保证安全性,又能保存数据,就引入了 Cookie,Cookie 也是按照硬盘文件的形式保存数据的,但是浏览器对这个文件进行了封装,网页只能往 Cookie 中存放键值对。
Cookie 往往是从服务器返回的数据(也可以是自己生成的);Cookie 存储在浏览器所在的本地计算机中,并且是按照域名为维度来存储的,每个域名都有自己的 Cookie ,彼此之间互不影响;Cookie 中的键值对是程序员自定义的;后续在请求这个服务器的时候,就会把 Cookie 中的内容自动带入到请求中,然后发给服务器,服务器通过这个 Cookie 中的内容做出一些逻辑上的处理。