说一下GET请求和POST请求的区别

面试官常常会问到的一个问题就是:GET请求和POST请求的区别。因为一个看似简单的问题就能考察出面试者对网络协议和通信的掌握程度以及对前后端开发基础知识是否了解、安全性意识是否足够强,以及综合分析与总结能力等。

所以答的好可以让面试官对你刮目相看,答不好很可能马上就被面试官心里pass掉了。

所以接下来我们就来好好回答一下这个问题!!

浏览器回退表现不同:GET在浏览器回退时是无害的,而POST会再次提交请求。

当我们在浏览器中使用GET方法进行页面请求时,浏览器会将请求参数附加到URL的查询字符串中,并通过HTTP协议发送给服务器。由于GET是一种幂等的操作,即多次执行同一个GET请求不会产生副作用或改变服务器状态。

因此当我们点击浏览器的回退按钮后重新加载之前访问过的页面时,浏览器会自动从缓存中获取该页面并显示出来。

相反地,当我们使用POST方法提交表单数据或执行某些非幂等操作时,浏览器会将请求参数包含在HTTP请求体中,并发送给服务器。POST可能导致对服务器状态进行更改、资源创建、更新或删除等重要操作。

因此,在当我们点击回退按钮返回到之前访问过的页面时,浏览器默认行为是再次向服务器发送相同的POST请求以保证执行那个特定操作。

当然这种区别是由浏览器和HTTP规范所决定的默认行为。但我们需要注意的是,并非所有情况下都遵循这样的原则。具体而言:

  • GET 请求也可以被缓存起来,取决于 HTTP 响应头部设置。
  • 在 POST 请求上添加合适响应头(例如 Cache-Control: no-store)可以阻止其被缓存。
  • JavaScript 或其他客户端脚本可以修改默认行为并控制如何处理历史记录和回退按钮事件。

GET产生的URL地址可以被Bookmark(即书签保存),而POST不可以。

当我们使用GET发送请求时,所有的参数都会附加在URL后面,并以键值对形式进行传递。例如:

js 复制代码
http://example.com/page?param1=value1&param2=value2

这意味着浏览器中会显示的完整URL,URL中包含了全部的参数信息,因此我们可以将该URL添加到书签或者通过复制粘贴方式共享给其他人。

相比之下,当我们使用POST请求时,参数数据并没有直接附加在URL上。相反,在HTTP消息体中以表单形式发送给服务器。由于POST请求不会把参数暴露在URL上,所以无法直接被我们保存为书签。

虽然POST不能直接请求保存为书签,但仍然有一些其他的方法来共享一个包含POST请求的链接。我们可以通过电子邮件、即时通讯应用程序等手段将链接分享给他人,并且他们可以点击该链接打开页面并进行相关操作。

浏览器对请求地址的处理不同:GET请求会被浏览器主动cache,而POST不会,除非手动设置。

当浏览器发送GET请求时,如果该请求的URL和参数与之前已经访问过的URL和参数相匹配,则浏览器会尝试从本地缓存获取响应结果。

这是因为GET请求通常被认为是无副作用(不改变服务器状态或资源)且幂等(多次执行产生同样结果)的操作。

由于幂等性,浏览器认为可以安全地使用上次获取到的响应结果,并避免再次向服务器发起请求。

相反,当浏览器发送POST请求时,默认情况下不会将其结果缓存。

这是因为POST通常具有副作用(可能会更改服务器状态或资源),而且不具备幂等性。如果每次都直接使用缓存结果,则可能导致数据不一致或意外操作。

然而,在某些特殊情况下我们希望能够对POST请求进行缓存以提高性能或减少网络流量消耗。

在这种情况下, 我们可以通过设置 Cache-Control 和 Expires 等HTTP头字段来告诉浏览器是否可以对POST响应进行缓存,并指定有效期限。

例如:

ini 复制代码
POST /api/submit HTTP/1.1
Host: example.com
Cache-Control: max-age=3600

在上面这个例子中,通过设置 Cache-Control 为 max-age=3600,我们告诉浏览器可以将该POST请求的响应结果缓存,并且有效期限是3600秒。

需要注意的是,虽然可以手动设置POST请求进行缓存,但仍需谨慎使用。

因为对于具有副作用和非幂等性的操作,默认不进行缓存是出于安全数据一致性方面的考虑。

如果确实需要对特定类型的POST请求进行缓存,我们需要确保了解其影响,并在设计时考虑清楚相关风险与利益。

编码方式不同:GET请求只能进行url编码,而POST支持多种编码方式。

我们在使用GET请求时会将参数附加到URL的查询字符串中,以便将其发送给服务器。

GET请求会把参数进行URL编码(也称为百分号编码或URL转义),以确保特殊字符不会干扰URL结构。以及URL编码会使用%符号后跟两个十六进制数字来表示非ASCII字符或某些特殊字符。 例如

ini 复制代码
GET /search?query=hello%20world HTTP/1.1
Host: example.com

hello world这个查询词被进行了URL编码(%20代表空格)并作为参数传递给服务器。

POST请求:

POST请求将数据作为消息正文发送到服务器,并且我们可以使用多种不同的数据编码方式来对消息体进行格式化。

最常用的POST数据编码方式是 application/x-www-form-urlencoded ,它与GET相似,也会对非ASCII字符和特殊字符进行URL编码。

这种方式下,参数按照键值对形式出现在消息正文中,并用&符号连接起来。

makefile 复制代码
POST /submit HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

name=John+Doe&age=25

浏览器对响应的处理不同:GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

当我们使用GET请求时,参数会附加在URL的查询字符串中,并显示在浏览器地址栏中。例如:

ini 复制代码
https://example.com/search?q=keyword

这意味着GET请求的参数将作为查询字符串一部分出现在URL上。

由于浏览器通常会将访问过的网址保存到历史记录中,因此包含参数的URL也会被完整地保留下来。

相比之下,POST请求通过HTTP消息主体传递参数,并不直接暴露给用户或显示在地址栏上。因此,在用户查看浏览器历史记录时,并没有POST请求所携带的具体参数信息可见。

参数大小不同:GET请求在URL中传送的参数是有长度限制的,而POST没有。

GET请求本身是没有长度限制的,但是URL有。不同的浏览器对于GET的长度限制也不一样。

yaml 复制代码
    IE:对IE浏览器URL的最大长度为2083个字符。
    Firefox:对Firefox浏览器URL的最大长度为65536个字符。   
    Safari: 对Safari浏览器URL的最大长度为80000个字符。   
    Opera:  对Opera浏览器URL的最大长度为190000个字符。
    Google(chrome):对Google浏览器URL的最大长度为8182个字符。  

所以,在需要兼容IE的情况下,URL请求的长度最长只能有2083个字符。

参数的数据类型不同:对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

GET方法通常用于从服务器获取数据,并且将参数附加到URL的查询字符串中。由于URL是以ASCII字符编码表示的,因此GET请求只接受ASCII字符作为参数值。

例如,在下面的URL中:

ini 复制代码
http://example.com/search?keyword=hello&category=1

keyword 和 category 是两个参数名,而 hello 和 1 是它们对应的值。这些值需要进行URL编码,以确保它们只包含有效的ASCII字符,并且不会破坏URL结构。

而POST方法与GET不同,POST请求将参数放置在HTTP请求正文(body)中发送给服务器。正文可以包含任何类型的数据,并没有限制为ASCII字符。

通过POST方法发送数据时,通常使用表单(form)来组织数据并将其封装在表单字段(field)中。

例如,在HTML登录表单中:

html 复制代码
<form action="http://example.com/submit" method="post">
    <input type="text" name="username" value="John Doe">
    <input type="password" name="password">
    <input type="submit" value="Submit">
</form>

当用户填写用户名和密码后点击提交按钮时,浏览器会向服务器发送一个POST请求,并将用户名和密码作为非限制性ASCII字符一起发送到服务器。

所以GET方法只接受ASCII字符作为参数值,并将参数附加到URL的查询字符串中。而POST方法没有限制数据类型,并且通过HTTP请求正文发送数据给服务器。

安全性不同:GET参数通过URL传递,POST放在Request body中,GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

我们在使用GET请求时,参数会直接附加在URL后面,在浏览器地址栏中可见。

而使用POST请求时,参数通过HTTP消息体进行传输,并不会直接显示在URL上。

所以可以说,在网络环境下(如公共Wi-Fi),GET请求可能更容易遭受恶意截获或拦截。

并且GET请求将参数作为查询字符串明文展示在URL中,这些URL很容易被缓存、保存到历史记录或者日志文件中。

如果包含敏感信息的URL被泄露、共享或者留存在公开场合,则可能带来安全隐患。

产生数据包不同:GET产生一个TCP数据包;POST产生两个TCP数据包。

GET请求产生一个TCP数据包

当客户端发送GET请求时,它会向服务器发起一个简单的HTTP请求,并将该请求封装在一个TCP数据包中发送给服务器。这个TCP数据包通常由三部分组成:源IP地址、目标IP地址以及HTTP GET请求。

POST请求产生两个TCP数据包

在使用POST方法时,客户端首先会发送一个带有POST方法和要传输的内容长度等信息的HTTP头部(Header)信息,然后再将实际需要传输的内容作为消息体(Body)放到第二个TCP数据包中并发送给服务器。

  • 第一个 TCP 数据包: 包含了 HTTP 头部, 用于告知服务器采用 POST 方法,并携带相关信息如Content-Length等。

  • 第二个 TCP 数据包: 包含了实际要传输的内容(即消息体),比如表单提交或上传文件等。

但是这些缺陷与不同其实都不是它们天生就是如此的,而是后天人为造成的。为什么这么说呢?接下来听让我扒开GET和POST的外衣,让你好好看清楚就知道了。

首先我们要知道GET和POST是什么?

GET和POST是HTTP请求的两种方法

那HTTP又是什么?

HTTP是基于TCP/IP的关于数据应该如何在互联网中传输的协议。

既然HTTP的底层是TCP和IP。那么我们的GET和POST的底层也应该是TCP和IP,也就是说,GET请求和POST请求底层都是通过TCP链接的。GET和POST的功能是一样的。如果我们要给GET加上request body,给POST带上url参数,技术上是完全行的通的。

既然如此,那么我们上面所说的那些区别又是怎么回事呢?你是否也很矛盾?

其实很好理解

在我们广阔的互联网世界中,TCP就像是汽车一样。我们使用TCP来传输数据,它非常可靠,从不会发生丢失或损坏的情况。

但是如果所有行驶在路上的汽车看起来都完全相同,那这个世界将变得一片混乱。

例如,急需送货物的汽车可能会被前面满载货物的汽车拦截在路上,整个交通系统可能会瘫痪。为了避免这种情况发生,在这个互联网世界中诞生了一个叫做HTTP的交通规则。

HTTP给予汽车运输设定了多种服务类别,其中包括GET、POST、PUT和DELETE等方法。

根据HTTP规则,在执行GET请求时,需要给汽车贴上GET标签(设置method为GET),并要求将要传递的数据放置在车顶位置(URL中)以便记录和查找。而对于POST请求,则需要贴上POST标签,并将货物放置在车厢内部。

当然,在执行GET请求时也可以偷偷地把一些货物藏进车厢里面去,但这显然是不道德的行为;同样地,在执行POST请求时也可以把一些数据放置到URL中去让人感觉有点愚蠢。

值得注意的是,HTTP仅仅是一套行为准则,而TCP才是实际上实现GET和POST等方法的基础。

所以,这些缺陷与不同其实都不是它们天生就是如此的,而是后天人为规定造成的。所以当面试官问我们get和post有什么不同时我们应该回答上面所说的9种不同,但是我们脑子里要清晰的知道它们其实是一样的,只是后天的人为规定造成了它们之间的不同和缺陷

相关推荐
鑫~阳40 分钟前
html + css 淘宝网实战
前端·css·html
Catherinemin44 分钟前
CSS|14 z-index
前端·css
VVVVWeiYee1 小时前
项目2路由交换
运维·服务器·网络·网络协议·信息与通信
2401_882727572 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder2 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂3 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand3 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL3 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
六卿3 小时前
react防止页面崩溃
前端·react.js·前端框架
z千鑫3 小时前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js