get和post区别?

”get是从服务器上获取数据,post是向服务器传送数据“(网上的回答),这句话post请求就不从服务器获取数据了?现在我是这么理解get和post:都是想服务器提交数据,并且都会从服务器获取数据,唯一的区别就是传送方式不同,get通过地址栏传输,post通过报文传输。这么理解对吗?求大神指点。。

post 和get请求的区别(html)? - 计算机网络 相似问题


刚好最近比较系统的研究了一下HTTP协议里GET和POST方法的区别,以下内容摘抄自我的博客:HTTP协议中GET和POST方法的区别 - Sunshinevvv"s Blog ,本文记录了我的探究历程,没有耐心的童鞋可以直接翻到最后看结论:语义之争

------------------以下是博客正文-----------------

HTTP协议中GET和POST方法的区别已经是老生常谈了,也是面试热门问题,我之前对此也只有一个粗浅的印象,这里来认真探讨一下。

通常的理解

w3schools关于这个问题的解答:HTTP 方法:GET 对比 POST 列出了一般的理解,比如:

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 中。

这个对比整体没什么毛病,但只是给出了一些现象上的区别,但并没有解释为什么,对于这个问题的理解不能就停在这一层。

理解错了?

有一篇文章99%的人理解错 HTTP 中 GET 与 POST 的区别,否定了上述回答:“很遗憾,这不是我们要的回答!”,作者说:

GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 GET和POST还有一个重大区别,简单的说:GET产生一个TCP数据包;POST产生两个TCP数据包。

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

都讲到TCP了,感觉很高大上有木有,起码当时看到这篇文章的我是信了的。

反转??

但是在逛知乎时又看到了这篇文章:听说『99% 的人都理解错了 HTTP 中 GET 与 POST 的区别』??,指出了前文的两个错误:

100 continue 只有在请求里带了Expect: 100-continueheader 的时候才有意义。

When the request contains an Expect header field that includes a 100-continue expectation, the 100 response indicates that the server wishes to receive the request payload body, as described in Section 5.1.1. The client ought to continue sending the request and discard the 100 response. If the request did not contain an Expect header field containing the 100-continue expectation, the client can simply discard this interim response.

我们通常在讨论 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,specification,implementation这些高端词汇,这下子我这个吃瓜群众再也坐不住了,决定亲自去研究一下。

RFC探秘

首先,什么是RFC呢?Wiki上面的定义是:

征求意见稿(英语: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 协议/版本 这样的格式,具体内容可以参见之前写的《图解HTTP》读书笔记里面的内容,凡是符合这个格式的请求都是合法的。

语义则定义了这一类型的请求具有什么样的性质。比如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」的对比 。

关于这两种方法的语义,RFC7231里原文已经写得很好了:

The GET method requests transfer of a current selected representation for the target resource. GET is the primary mechanism of information retrieval and the focus of almost all performance optimizations. Hence, when people speak of retrieving some identifiable information via HTTP, they are generally referring to making a GET request.

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

The POST method requests that the target resource process the representation enclosed in the request according to the resource’s own specific semantics.

勉强渣翻一下,再加上点自己的理解:

GET的语义是请求获取指定的资源。GET方法是安全、幂等、可缓存的(除非有 Cache-ControlHeader的约束),GET方法的报文主体没有任何语义。

POST的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST不安全,不幂等,(大部分实现)不可缓存。为了针对其不可缓存性,有一系列的方法来进行优化,以后有机会再研究(FLAG已经立起)。

还是举一个通俗栗子吧,在微博这个场景里,GET的语义会被用在「看看我的Timeline上最新的20条微博」这样的场景,而POST的语义会被用在「发微博、评论、点赞」这样的场景中。


1. 最直观的就是语义上的区别,get用于获取数据,post用于提交数据。

2. get参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限制),而post无限制

详细说下第一点,先说结论:颠倒两者会造成非常糟糕的结果。

比如一个网页地址是:

http://www.taobao.com?itemId=123

你把它发给朋友,说这个东西很酷!这就是用get来获取数据最正确的方式,它有利于传播。

但如果你用post请求获取到一个商品页面,url还是

http://www.taobao.com

那你把这个url分享给朋友是没有意义的。

反过来说,如果你用

http://www.weibo.com?uid=1content=hahatoken=xxxxxxxxxx

来发一条内容为haha的微博,并且这个url被其他人看到了。

那他直接把url在他那儿复制一下就可以帮你发微博了,是不是也很不合理?

==============

UPDATE 2017.1.24:

根据 @mingxu chen 的建议,修改部分描述。



http协议可不止get和post,还有put或者delete等,参考restful的api设计

但请注意,get和post的设计意图是什么。根据http的设计,大家在看到get的时候,都期望这个请求对服务器没有修改,看到post的时候,都认为这对服务器产生了修改。

期望在这里是重点,因为这遵守了http协议设计的概念完整性,容易被其他人理解。当然,也可以说这有利于安全性等方面,但这比较次要。

你提到传参方式的不同,某种程度上这确实是一个区别,但请注意,协议并没有规定get一定要用url传参数,也没有规定post要用请求体传参数。

实际上倒过来也完全可以,合法,最多语言api里头可能是不那样友好罢了。语言api不少只区分是从url提交的还是从请求体提交的,不管get或者post

而且这不是默认的做法,约定优于特立独行。

请注意,概念完整性的必要性再强调也不为过。

所以有时候我们不那样做,实际上并不是不允许那样做…而是大家都不那样做罢了


区别是get多少次都不应改变页面呈现的数据,post会。所以post需要token来防止跨站请求漏洞。


GET和POST长度的限制问题

GET

1.GET是通过URL提交数据,因此GET可提交的数据量就跟URL所能达到的最大长度有直接关系。

2.实际上HTTP协议对URL长度是没有限制的;限制URL长度大多数是浏览器或者服务器的配置参数

POST

1.同样的,HTTP协议没有对POST进行任何限制,一般是受服务器配置限制或者内存大小。

2.PHP下可以修改php.conf的postmaxsize来设置POST的大小。

请求header的content-length问题

如果有人恶意伪造content-length很大的包头,但实际上发送content-length很小的请求,这样服务器会一直干等,直到超时。当然服务器是可以通过设置来避免该问题的

GET和POST的安全性

1.GET是通过URL方式请求,可以直接看到,明文传输。

2.POST是通过请求header请求,可以开发者工具或者抓包可以看到,同样也是明文的。 3.GET请求会保存在浏览器历史纪录中,还可能会保存在Web的日志中。

GET和POST对服务器的状态

根据http的设计,大家在看到get的时候,都期望这个请求对服务器没有修改,看到post的时候,都认为这对服务器产生了修改。

GET幂等,POST不幂等

幂等是指同一个请求方法执行多次和仅执行一次的效果完全相同。

1.按照RFC规范,PUT,DELETE和安全方法都是幂等的。虽说是规范,但服务端实现是否幂等是无法确保的。

2.引入幂等主要是为了处理同一个请求重复发送的情况,比如在请求响应前失去连接,如果方法是幂等的,就可以放心地重发一次请求。这也是浏览器在后退/刷新时遇到POST会给用户提示的原因:POST语义不是幂等的,重复请求可能会带来意想不到的后果。

3.比如在微博这个场景里,GET的语义会被用在「看看我的Timeline上最新的20条微博」这样的场景,而POST的语义会被用在「发微博、评论、点赞」这样的场景中。


你能用GET进行更新操作 也能用POST进行查询操作 但是那不是这俩Method的本意 前者是获取、 后者是更新 获取时提供的是参数(queryString) 更新则是表单


都是向服务器发送请求嘛, Get是向服务器发送索取数据的一种请求,而Post是向服务器提交数据的一种请求


GET与POST的区别kimmking.github.io

对比项

  1. 参数:
  • GET传递的参数只能带URL后面,文本格式QueryString,各浏览器一般有长度限制,一般认为是2083,如果有中文字符更短。提交到服务器端的数据量小。参考:https://www.cnblogs.com/henryhappier/archive/2010/10/09/1846554.html
  • POST可以传递application/x-www-form-urlencoded的类似QueryString、multipart/form-data的二进制报文格式(支持文件信息嵌入报文传输)、纯文本或二进制的body参数。提交到服务器端的数据量大。参考:http://blog.csdn.net/kimmking/article/details/2051169
  1. 用途:
  • GET用于从服务器端获取数据,包括静态资源(HTML|JS|CSS|Image等等)、动态数据展示(列表数据、详情数据等等)。
  • POST用于向服务器提交数据,比如增删改数据,提交一个表单新建一个用户、或修改一个用户等。
  1. 缓存:
  • GET时默认可以复用前面的请求数据作为缓存结果返回,此时以完整的URL作为缓存数据的KEY。所以有时候为了强制每次请求都是新数据,我们可以在URL后面加上一个随机参数Math.random或时间戳new Date().getTime()、或版本号,比如abc.com?a=1rnd=0.123987之类的。这也是目前一些静态资源后面加一个很长的版本号的原因,jquery-min.js?v=13877770表示一个版本,当页面引用jquery-min.js?v=13877771时浏览器必然会重新去服务器请求这个资源。jQuery.ajax方法,如果cache=false,则会在GET请求参数中附加”_={timestamp}”来禁用缓存。
  • POST一般则不会被这些缓存因素影响。
  1. 安全性:
  • 默认对于nginx的access log,会自动记录get或post的完整URL,包括其中带的参数。
  • 对于POST来说,请求的报文却不会被记录,这些对于敏感数据来说,POST更安全一些。
  1. 自动化性能测试:
  • 基于上面提到的nginx日志,可以使用grep GET+日期,awk格式化,然后sort -u去重,从而提取到某天的所有GET请求URL,使用程序模拟登陆,然后请求所有URL即可获取简单的性能测试数据,每个请求是否正确,响应时间多少等等。
  • 但是对于POST请求,因为不知道报文,无法这样简单处理。可以通过nginx-lua获取报文输出到log,这样格式化会麻烦很多,但不失为一个办法。


首先我是小白.....请各位大佬指教。

说到底,我觉得是要正确理解“GET的页面”和“POST的页面”的区别。

要说清楚这两个区别,首先要说清楚一个概念——你输入内容的页面和没输入内容的页面是两种东西。

当你进入一个有表单的页面时,假如其URL是"http://www.haha.com",你把这个URL分享给朋友,朋友进入这个页面看到的所有内容将和你看到的一摸一样;

此时你在表单里输入你的名字,没有提交,URL还是“www.haha.com”,此时有两种情况:

1.这个表单的method值是POST。你把这个URL分享给朋友,朋友看到的是和你不一样的页面(页面表单里没有你的名字,除此之外一摸一样)。

2.这个表单的method值是GET。你把这个URL分享给朋友,朋友看到的页面和你的还是不一样(GET能本地缓存(应该没有“联网缓存”)——在某些应用里,关闭网页后再次进入,你会看到一个有你名字的表单。QQ空间网页版就是这样,你在说说处输入内容但不发布,重新打开时你还能看到那个没发布的内容。当然,你清除浏览器的Cookie和网站记录后再次进入这个页面就看不到未发布的内容了)。

现在,你把表单提交了(注意,有时候你可能都不知道自己提交了这个表单,比如百度搜索里,回车就是提交~),有两种情况:

1.表单的method是POST,URL变成了“http://www.haha.com/nimei.php”。此时页面被刷新,你的数据被提交服务器脚本返回给你一个新页面。此时就算你“后退”到“www.haha.com”也看不到你原来输入了内容的那个表单了;你把这个网页分享给朋友,朋友是看不到你的页面的(你这个页面必须是提交相同的数据后才能看到),这也是为什么你登陆微博后,直接复制地址栏的URL发给别人,别人看不到这个网页的原因。

2.表单的method是GET,URL变成了“http://www.haha.com/nimei.php?name="haha".....”。此时页面被刷新,同样得到一个新页面。如果你“后退”,你能看到原来输入了内容的表单;你可以保存为书签,关闭后再次打开能看到保存书签时的网页(因为URL里有你发给服务器脚本的所有数据,就相当于再次发送给服务器脚本相同的数据,返回的页面自然也就一样——服务器脚本处理这些数据得到的结果还是一样的话);你可以把这个页面分享给朋友,朋友打开后能看到一摸一样的页面(理由和书签里说的一样)

基于上述观点,我再看网上关于POST和GET的讨论时,感觉好多了...............


我觉得先从语义方面进行区分吧,具体请移步阮一峰的RESTful API设计指南里Http动词一节。我觉得写得挺好的。

RESTful API 设计指南

简单的从语义上来说get是获取资源,post是新建一个资源。get是幂等的,post不幂等。

当然RFC标准中还有其他动词,比如用于更新的put(幂等)、delete等


HTTP协议对GET和POST都没有对长度的限制,而对于URL长度上的限制是浏览器跟服务器造成的。

Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求,在FORM(表单)中,Method默认为"GET",实质上,GET和POST只是发送机制不同,并不是一个取一个发!

浅谈HTTP中Get与Post的区别


请求报文不同,请求方式不同,安全级别不同


最基本的解释:get是向服务器端请求数据,post是提交数据。


推薦閱讀:

零基礎開始學 Web 前端開發,有什麼建議嗎?
看某前端設計書上說,在 base.css 里先定義一些基礎樣式然後在 html 裡面加上相應的 class,這樣是否和語義化相矛盾?
如何用django在雲虛擬主機上建站?
樹莓派做web伺服器的話,性能怎麼樣?
網站中的簡體繁體切換是如何實現的?

TAG:Web开发 | Ajax | HTTP |