http幂等性
和本地环境相比,在分布式系统中,我们不能轻易不能保证分布式环境的可靠性。例如服务器端的返回结果由于网络等原因丢失了,导致客户端无法得知处理结果。在网页上,一些不恰当的设计可能会让用户认为上一次操作失败了,然后刷新页面,这就导致了接口被调用两次。如果使用幂等性方案,则将操作分成两个步骤:
- 获取本次操作的id。
- 使用本次id进行操作。
HTTP协议本身是一种
面向资源
的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是
RESTful
的,它把HTTP当成
应用层协议
,比较忠实地遵守了HTTP协议的各种规定;另一种是
SOA
的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了
传输层协议
,然后在HTTP之上建立了自己的应用层协议。
GET
方法用于
获取资源
,不应有副作用,所以
是幂等
的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。
GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。
DELETE
方法用于删除资源,有副作用,但它满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
语义上,“
POST
表示创建资源,
PUT
表示更新资源”;而实际上,二者
均可用于创建资源
,更为本质的差别是在
幂等性
方面:
POST所对应的
URI
并非创建的资源本身,而是
资源的接收者
。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法
不具备幂等性
。
而PUT所对应的
URI
是要
创建或更新的资源本身
。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,
PUT方法具有幂等性
。
301 302
理论上
,由于POST 方法不符合幂等性,客户端收到服务端的 302 状态码,不应该自动的向新的 URI 发送重复请求,必须跟用户确认是否该重发,因为第二次 POST 时,环境可能已经发生变化,POST 操作会不符合用户预期。
但是很多浏览器(user agent),并不按规定来,会自动用GET方法重定向到location指定的url。就是说现存的很多浏览器在遇到POST请求返回301、302状态码的时候
自动用GET请求location中的url
,无需用户确认。
303 307
为了解决浏览器不遵循规范的问题,在http1.1中,增加了303 307两个状态码。
303
:
当浏览器收到303时,可以继续保持浏览器自动发送GET请求这种不规范的用法。
307
:
当浏览器收到307时,则强制浏览器必须先征求用户确认再发送请求。