get与post需要注意的几点

在面试或者笔试时,经常会被问到 HTTP 方法中 get 和 post 的异同点。本文简单整理归纳了一下,以备忘。

1、"get/post" VS "web 中的 get/post"

一些 web 相关职位的面试,无论有没有提 web,面试中的 get/post,一般就是指 web 中的 get/post。需要注意的是,web 中的 get/post 只是 http 中的 get/post 的子集,所以如果谈 get 与 post 的区别,要是面试官有心挖坑,就要特别注意下你们聊的是不是 web 中的 get/post。(本文接下去讲的 get/post 基本上是基于 web 的)

关于 get/post,可以查看 rfc-2616 了解详情:

其实,http 中的 get 与 post 只是单纯的名字上的区别,get 请求的数据也可以放在 request body 中,只是浏览器没有实现它,但是 get 并不只是在 web 中使用。所以,说到 get/post 的区别,会直接条件反射地去说 web 中的 get/post 区别。而 web 中 get 以及 post,其实都可以往服务端发送数据,get 是将数据拼接在 url 上(有必要时需要 encode),而 post 是将数据封装在 request body 中,发送过去。

get/post 可以顾名思义地理解,get 是用来请求数据,那么,既然是请求数据,为什么还要带上数据呢?其实很好理解,比如一个新闻页面,有很多内页,那么 get 请求可能带上的类似这样的参数 page=1,即为请求第一页的数据。post 的话顾名思义就是发送数据,所以需要带上数据。

2、get 请求是安全和幂等的

何谓安全?这里的安全指的是在规范的定义下,get 操作不会修改服务器的数据,无论做多少次 get 请求,服务端的数据都是不会有变化的,所以说 get 请求是安全的。"get 请求是安全的" 换句话说就是 "get 请求不产生副作用",它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。

何谓幂等?幂等是说,同一个请求原封不动的发送 N 次和 M 次(N 不等于 M,N 和 M 都大于 1),服务器上资源的状态最终是一致的,相应地服务器返回的内容也是一致的。get 请求是幂等的,因为无论请求多少次,服务器上的资源状态不变,而 post 则不然,post 会更新服务器的数据。比如发贴是非幂等的,重复 10 次发贴请求会创建 10 个帖子。但修改帖子内容是幂等的,一个修改请求重放无论多少次,帖子最终状态都是一致的。

关于幂等再举个数学上的例子。对于单目运算,如果一个运算对于在范围内的所有的一个数多次进行该运算所得的结果和进行一次该运算所得的结果是一样的,那么我们就称该运算是幂等的。比如绝对值运算就是一个例子,在实数集中,有 abs(a)=abs(abs(a))。这个例子非常的好,abs(a) 可以表示做了一次 get 请求后的服务器上的资源状态,对其继续做 abs 运算,状态不变,这就好比做了一次 get 请求,继续再做,而该资源状态一直不变,所以请求得到的东西也就不会变。

因此,按照某一 ID 阅览文章就是安全而幂等的,应当使用 get。而注册用户、登录等操作会改变服务器的资源状态,不是安全而幂等的,应当使用 post。

3、post 相对 get 请求是 "安全" 的

这里的 "安全",和第二点所讲的 "安全" 又是两回事了。这里的 "安全" 是密码学上的,也就是大多数场景中 "安全" 的意思。

其实该点颇有点(post)五十步笑(get)百步之嫌。

我们知道,get 请求是将数据附在 url 上,而 post 是将数据封装在 request body 中。所以 get 请求附加的参数可能会被人在浏览器地址栏上直接看到,或者查看一下浏览器的历史记录或者日志,就能看到你的参数。而 post 因为不能被缓存,也不能被保存为书签,所以请求过了就没有记录了?请求参数就不能被截获了?非也,抓个包就可以看到了。

所以,post 请求只是相对安全的。(防君子防不了小人)

4、get 请求发送数据更小

http 协议中的 get/post 并没有发送数据大小的限制,对发送数据大小产生限制的是浏览器以及操作系统、服务器,http 本身并没有对 url 长度有所限制

IE 对 URL 长度的限制是 2083字节(<=IE 8)。对于其他浏览器,如 Netscape、FireFox 等,理论上没有长度限制,其限制取决于操作系统以及服务器的支持。而 chrome 遇到长度很长的 URL 时,会直接 崩溃

URL 长了,对服务器处理也是一种负担。原本一个会话就没有多少数据,现在如果有人恶意地构造几个几 M 大小的 URL,并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是,把告诉服务器 Content-Length 是一个很大的数,然后只给服务器发一点儿数据,嘿嘿,服务器你就傻等着去吧。哪怕你有超时设置,这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给 URL 长度加限制。

理论上讲,POST 是没有大小限制的,HTTP 协议规范也没有进行大小限制,说 "POST数据量存在80K/100K 的大小限制" 是不准确的,POST 数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

5、get 能被缓存,post 不能被缓存

这点非常容易理解,打开一个页面,如果之前打开过,那么很明显速度会加快,这是因为 html/js/css/img 等文件都能被浏览器缓存(也可以被服务器缓存),而这些文件的获取,都是用的 get 请求。事实上,web 中的绝大多数请求都是用 get 完成的,post 请求目前为止我只是在 ajax 以及 form 表单中有见过。

但是实际上,http 协议中 post 和 get 都是可以被缓存的,不过不要惊讶,浏览器的实现总是比标准厉害。(post 和 get 真的只有名字上的区别啊。。)

因为 get 请求会有缓存,所以在开发过程中,很多时候我们要手动清除缓存,不然看不到修改后的样子。

关于 get 请求能被缓存我有个惨痛的经历。在一次开发中,要做一个跳转页面(假设为 a.index,同时需要在主页面(假设为 index.htm)中带个参数(假设为 tmp)过去,为了方便,直接将参数附加在了跳转页面的 url 上,页面地址为 a.htm?tmp,直接取其 location.search 属性即可获取参数。之后修改了 a.htm 页面的内容,但是发现一直不生效,并且已经清除了 a.htm 页面的缓存,排查了很久,原因很显然,缓存地址为 a.htm?tmp,需要清除该地址的缓存!

所以一般要获取最新的文件(非缓存文件),可以加个类似时间戳一样的参数。

6、form 表单可以用 get 提交

form 表单有个 method 属性,一般为 "post"。但是,其实 method 属性是可以为 "get" 的,甚至,默认就是 "get"。

如果是 "post" 方式,数据藏在 request body 中,如果是 "get" 方式,数据拼接在 url 上。但是,一般 form 表示都与 "数据提交" 相辅相成,会对服务端数据做修改,所以一般都是以 "post" 的方式。

7、求他:put 以及 delete

说完 get/post,再来简单谈谈他们的其他几个好基友吧。

Http 定义了与服务器交互的不同方法,最基本的方法有 4 种,分别是 GET,POST,PUT,DELETE。URL 全称是资源描述符,我们可以这样认为:一个 URL 地址,它用于描述一个网络上的资源,而 HTTP 中的 GET,POST,PUT,DELETE 就对应着对这个资源的查,改,增,删 4 个操作。

  • GET:无副作用,幂等,不可带 Request Body
  • PUT:副作用,幂等,可以带 Request Body
  • POST:副作用,非幂等,可以带 Request Body
  • DELETE:副作用,幂等,不可带 Request Body

8、Read More

原文链接:http://www.cnblogs.com/zichi/p/5229108.html (文章来源)

随机推荐

  1. leetcode 300最长上升子序列

    用递归DFS遍历所有组合肯定积分会超时,原因是有很多重复的操作,可以想象每次回溯后肯定会有重复操作.所以改用动态规划.建立一个vector<int>memo,初始化为1,memo[i]表示 ...

  2. gcc 6.2.0/6.3.0/8.2.0 编译安装

    参考:http://www.linuxfromscratch.org/blfs/view/stable/general/gcc.html 下载地址在这里:https://ftp.gnu.org/gnu ...

  3. vue中使用elementui里的table时不被选中设置

    情景:例如提现列表,转账失败后转账金额直接返回用户余额,所以当前数据不可以再次操作 直接粘贴代码: <el-table-column type="selection" wid ...

  4. python入门之列表

    1.列表基本格式# list 类 列表li = [1, 2, 3, "sb", ["时间",[9, 10], "huang"], 6, 7, ...

  5. laravel 前后端分离 token

    由于自己开发的项目中用到了 JWT 技术,前端采用了 Vue.js 框架,后端采用了 CodeIgniter 框架,故作此文帮助使用相同技术栈的朋友们. 具体思路如下:把后端生成的 JWT token ...

  6. mysql存储过程或函数中传入参数与表字段名相同引发的悲剧

    真实案例.如下的一个存储过程: create procedure Apple(in user_id int) begin delete from users where user_id = user_ ...

  7. 通过改hosts访问wikipedia

    能访问https://www.wikipedia.org 大部分时候我们是可以访问的wikipedia的主页或是英文首页的,但中文页面却经常被墙,这时候你可以通过在命令行下ping www.wikip ...

  8. RepRap Prusa i3 平台自動補正

    RepRap Prusa i3 平台自動補正 平台校正不但費時,而且經常失敗,時在是很令人洩氣!期盼了好一陣子,Marlin終於將平台自動補正的功能加進來了!!這個功能將原本Z軸的Endstop,改裝 ...

  9. poj2114 寻找树上存在长度为k点对,树上的分治

    寻找树上存在长度为k点对,树上的分治  代码和  这个  差不多 ,改一下判断的就好 #include <iostream> #include <algorithm> #inc ...

  10. 多线程:Operation(二)

    1. Operation 设置依赖关系 先看看如何设置operation的依赖关系. 啥叫依赖关系?有啥用啊?打个比方咱们要做一个听音乐的付费App项目,需要经过登陆.付费.下载.播放四个步骤.其实一 ...