get和post两种请求方法的区别

最直观的区别就是GET把参数包含在URL中,POST经过request body传递参数。
语义上的区别,get用于获取数据,post用于提交数据。
get参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限制),而post无限制web

基于HTTP协议上解释以下:

w3schools关于这个问题的解答:浏览器

GET后退按钮/刷新无害,POST数据会被从新提交(浏览器应该告知用户数据会被从新提交)。
GET书签可收藏,POST为书签不可收藏。
GET能被缓存,POST不能缓存 。
GET编码类型application/x-www-form-url,POST编码类型encodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
GET历史参数保留在浏览器历史中。POST参数不会保存在浏览器历史中。
GET对数据长度有限制,当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。POST无限制。
GET只容许 ASCII 字符。POST没有限制。也容许二进制数据。
与 POST 相比,GET 的安全性较差,由于所发送的数据是 URL 的一部分。在发送密码或其余敏感信息时毫不要使用 GET !POST 比 GET 更安全,由于参数不会被保存在浏览器历史或 web 服务器日志中。
GET的数据在 URL 中对全部人都是可见的。POST的数据不会显示在 URL 中。

参数大小的限制是怎么回事:HTTP协议对GET和POST都没有对长度的限制,HTTP协议明确地指出了,HTTP头和Body都没有长度的要求。而对于URL长度上的限制,有两方面的缘由形成:
(1)、(大多数)浏览器一般都会限制url长度在2K个字节
(2)、(大多数)服务器最多处理64K大小的url。URL长了,对服务器处理也是一种负担。本来一个会话就没有多少数据,如今若是有人恶意地构造几个几M大小的URL,并不停地访问你的服务器。服务器的最大并发数显然会降低。另外一种攻击方式是,把告诉服务器Content-Length是一个很大的数,而后只给服务器发一点儿数据,嘿嘿,服务器你就傻等着去吧。哪怕你有超时设置,这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给URL长度加限制。可是这个限制是针对全部HTTP请求的,与GET、POST没有关系。 安全不安全和GET、POST没有关系缓存

其实这些只是一些现象上的区别,若是深刻了解,GET和POST本质上没有区别的安全

基于TCP协议上解释以下:

一、现代的Web Server都是支持GET中包含BODY这样的请求。虽然这种请求不可能从浏览器发出,可是如今的Web Server又不是只给浏览器用,已经彻底地超出了HTML服务器的范畴了。服务器

二、HTTP的底层是TCP/IP。因此GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP连接。GET和POST能作的事情是同样同样的。你要给GET加上request body,给POST带上url参数,技术上是彻底行的通的。网络

三、GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
这里有段引用:并发

由于POST须要两步,时间上消耗的要多一点,看起来GET比POST更有效。所以Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为何?app

  1. GET与POST都有本身的语义,不能随便混用。
  2. 据研究,在网络环境好的状况下,发一次包的时间和发两次包的时间差异基本能够无视。而在网络环境差的状况下,两次包的TCP在验证数据包完整性上,有很是大的优势。
  3. 并非全部浏览器都会在POST中发送两次包,Firefox就只发送一次。

此处引用另外一个解释:

首先强调下:协议不等于实现:协议规定安全在实现里不必定安全,协议规定幂等在实现里不必定幂等,协议规定可缓存在实现里不必定可缓存。curl

咱们一般在讨论 GET vs POST 的时候,实际上讨论的是 specification,而不是 implementation。什么是 specification?说白了就是相关的 RFC。implementation 则是全部实现了 specification 中描述的代码/库/产品,好比 curl,Python 的 requests 库,或者 Chrome。POST 请求怎么发送,根本就不是这段 RFC 在讨论的事情。RFC 中只说明了 100 continue 和 Expect header 的联系,好比你想在 GET 请求里带 body,同样能够发送 Expect: 100-continue 并等待 100 continue,这是符合标准的。也就是说,『XHR 发送两个 TCP packets』是关于 implementation 的知识,而不是关于 specification 的知识。你不能说『Chrome 在 AJAX POST 的时候会发两个 TCP packets,GET 只会发一个』是 GET 和 POST 的区别,正如你不能由于北京 PM 2.5 常常爆表就说国家关于工业废气排放的标准有问题。

什么是RFC呢?post

征求意见稿(英语:Request For Comments,缩写为RFC),是由互联网工程任务组(IETF)发布的一系列备忘录。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件,以编号排定。目前RFC文件是由互联网协会(ISOC)赞助发行。
简单理解RFC就是互联网的规范,咱们一般所说的「协议」就是以RFC的形式存在,而现行的HTTP/1.1规范的RFC有以下几个: RFC7230, RFC7231, RFC7232, RFC7233, RFC7234,RFC7235。 其中RFC7231里的Section 4. Request Methods涉及到了几个HTTP方法,接下来仔细阅读这一章节。
The request method token is the primary source of request semantics; it indicates the purpose for which the client has made this request and what is expected by the client as a successful result.

这里牵涉到一个很重要的词语:semantic 「语义」,那么什么是语义呢?这一篇文章给出了解释:语法和语义的区别。

一种语言是合法句子的集合。什么样的句子是合法的呢?能够从两方面来判断:语法和语义。语法是和文法结构有关,然而语义是和按照这个结构所组合的单词符号的意义有关。合理的语法结构并不代表语义是合法的。例如咱们常说:我上大学,这个句子是符合语法规则的,也符合语义规则。可是大学上我,虽然符合语法规则,但没有什么意义,因此说是不符合语义的。

对于HTTP请求来讲,语法是指请求响应的格式,好比请求第一行必须是 方法名 URI 协议/版本 这样的格式,

语义则定义了这一类型的请求具备什么样的性质。好比GET的语义就是「获取资源」,POST的语义是「处理资源」,那么在具体实现这两个方法时,就必须考虑其语义,作出符合其语义的行为。

固然在符合语法的前提下实现违背语义的行为也是能够作到的,好比使用GET方法修改用户信息,POST获取资源列表,这样就只能说这个请求是「合法」的,但不是「符合语义」的。 写到这里忽然联想到XML里面的两个概念:Well Formed和Valid,彷佛也正是语法和语义的理念呢。

上文说到方法是请求语义的主要来源,也便是还有次要来源,一些请求Header能够进一步修饰请求的语义,好比一个带上了 Range Header的GET请求就变成了部分请求。

RFC7231里定义了HTTP方法的几个性质:

  1. Safe - 安全。这里的「安全」和一般理解的「安全」意义不一样,若是一个方法的语义在本质上是「只读」的,那么这个方法就是安全的。客户端向服务端的资源发起的请求若是使用了是安全的方法,就不该该引发服务端任何的状态变化,所以也是无害的。 此RFC定义,GET, HEAD, OPTIONS 和 TRACE 这几个方法是安全的。可是这个定义只是规范,并不能保证方法的实现也是安全的,服务端的实现可能会不符合方法语义,正如上文说过的使用GET修改用户信息的状况。引入安全这个概念的目的是为了方便网络爬虫和缓存,以避免调用或者缓存某些不安全方法时引发某些意外的后果。User Agent(浏览器)应该在执行安全和不安全方法时作出区分对待,并给用户以提示。
  2. Idempotent - 幂等幂等的概念是指同一个请求方法执行屡次和仅执行一次的效果彻底相同。按照RFC规范,PUT,DELETE和安全方法都是幂等的。一样,这也仅仅是规范,服务端实现是否幂等是没法确保的。引入幂等主要是为了处理同一个请求重复发送的状况,好比在请求响应前失去链接,若是方法是幂等的,就能够放心地重发一次请求。这也是浏览器在后退/刷新时遇到POST会给用户提示的缘由:POST语义不是幂等的,重复请求可能会带来意想不到的后果。
  3. Cacheable - 可缓存性 顾名思义就是一个方法是否能够被缓存,此RFC里GET,HEAD和某些状况下的POST都是可缓存的,可是绝大多数的浏览器的实现里仅仅支持GET和HEAD。关于缓存的更多内容能够去看RFC7234。

在这三个特性里一直在强调同一个事情,那就是协议不等于实现:协议规定安全在实现里不必定安全,协议规定幂等在实现里不必定幂等,协议规定可缓存在实现里不必定可缓存。这其实就是上面那个做者提到的specification和implementation的关系。

走到这一步,其实就明白了要理解这两个方法的区别,本质上是 「语义」的对比而不是「语法」的对比,是「Specification」的对比而不是「Implementation」的对比 。

相关文章
相关标签/搜索