zoukankan      html  css  js  c++  java
  • 区分PATCH与PUT、POST方法

    区分PATCH与PUT、POST方法

      在HTTP原本的定义中[RFC2616],用于上传数据的方法只有POST和PUT。后来鉴于POST和PUT语义和功能上的不足,又加入了PATCH方法[RFC5789]。POST与PUT方法的差异是显而易见的,而PUT与PATCH方法就比较相似,但它们的用法却完全不同。
      PUT方法和PATCH方法所请求的目标地址都是直接指向资源的,而POST方法请求的目标是一个行为处理器,这点很容易区分。但PUT和PATCH呢?根据规范中所介绍的PUT用于替换资源,而PATCH用于更新部分资源。仅凭这个描述,我无法理解他们的区别,直到看到后面介绍PATCH是非幂等的时候才恍然大悟。
      从这里开始要考虑一个问题,PATCH为什么是非幂等的呢?POST方法非幂等可以理解,因为它请求服务器执行一个动作,多次发起请求可能导致动作多次执行。而像PATCH这样请求的目标是一个资源的,如果它只是更新一个资源,不执行其它动作,又何来不幂等呢?其实是我忽略了一个问题,PATCH方法和POST方法有个很相似的地方,它们的实体部分都是结构化的数据。POST方法的实体结构一般是 multipart/form-data 或 application/x-www-form-urlencoded 而PATCH方法的实体结构则随其它规范定义。这和PUT方法的无结构实体相比就是最大的区别。
      PUT方法的实体无结构的,它直接把实体部分的数据替换到服务器的资源上。而PATCH提供的实体则需要根据程序或其它协议的定义,解析后在服务器上执行,以此来修改服务器上的数据。也就是说,PATCH请求是会执行某个程序的,如果重复提交,程序可能执行多次,对服务器上的资源就可能造成额外的影响,这就可以解释它为什么是不幂等的了。
      举个例子,如果服务器上有个资源/abc.int,里面存放一个整数,值为 1。也就是说,GET这个资源的话,服务器响应的实体只包含了 1 这个数字。现在在自己的框架中定义当提交PATCH请求,实体匹配^+d+$的格式时就对服务器资源中的数字执行一个加法操作。于是当客户端向/abc.int地址发起PATCH请求,实体部分为+3之后,服务器的/abc.int资源中的数据就变成 4,也就是说,GET它会得到 4。如果客户端不小心重复提交了PATCH请求,那么+3就会被再执行一次,这个资源的数据就变成 7。

      这么一看,PATCH和PUT的区别就非常明显了吧。

    经常会混淆HTTP的POST/PUT方法,因为这两个方法似乎都可以用来创建或更新一个资源。

    POST 方法

    1.  
      用来创建一个子资源,如 /api/users,会在users下面创建一个user,如users/1;
    2.  
      POST方法不是幂等的,多次执行,将导致多条相同的用户被创建(users/1,users/2 ...
    3.  
      而这些用户除了自增长id外有着相同的数据,除非你的系统实现了额外的数据唯一性检查)

    PUT 方法

    1.  
      PUT比較正确的定义是 Replace (Create or Update),
    2.  
      例如 PUT /items/1 的意思是替换 /items/1 ,如果已经存在就替换,沒有就新增;
    3.  
      因此,PUT方法一般会用来更新一个已知资源,除非在创建前,你完全知道自己要创建的对象的URI

    http post put 区别

    **在HTTP中,PUT被定义为idempotent的方法,POST则不是,这是一个很重要的区别
    

    举个栗子:

    1.  
      POST /api/articles
    2.  
      PUT /gists/:id/stars
    3.  
      如果产生两个**资源**,就说明这个服务不是idempotent(幂等的),因为多次使用产生了副作用;
    4.  
      如果后一个请求把第一个请求**覆盖**掉了,那这个服务就是idempotent的。
    5.  
      前一种情况,应该使用POST方法;
    6.  
      后一种情况,应该使用PUT方法。

    PATCH 方法

    1.  
      PATCH方法是新引入的,是对PUT方法的补充,用来对已知资源进行**局部更新**
    2.  
      HTTP PATCH method require a feature to do partial resource modification.
    3.  
      The existing HTTP PUT method only allows a complete replacement of a document.

    需要注意的地方

    1.  
      **语义** 而非 风格;是语义的问题,换句话说:
    2.  
      也就是这取决于这个REST服务的行为是否是idempotent(幂等的)
    3.  
      // 但是这个只是在语义上,同时不要太苛求语义
    4.  
      DELETE 刪除,無論如何 资源 最後都将不复存在
    5.  
      // PUT 替換(新增或完整更新)
    6.  
      // PATCH 部分更新

    Examples from github api v3

    1.  
      create a gist
    2.  
      POST /gists
    3.  
       
    4.  
      star a gist
    5.  
      PUT /gists/:id/stars

    设计 restful api 需要注意的问题

    **名词复数**
    

    URIs

    names > verbs : 推荐使用具象化的名词而不是动词
    

    plural > singular

    1.  
      Resource collections: /v1/users
    2.  
      Resource instances: /v1/users/007

    注: idempotent 幂等的

    如果一个方法重复执行多次,产生的效果是一样的,那就是idempotent的;
    idempotent的意思是如果相同的操作再執行第二遍第三遍,结果还是一样的。

    so :

    人们通常(为徒省事)把一个包含了修改后userName的完整userInfo对象传给后端,做完整更新。但仔细想想,这种做法感觉有点二,而且真心浪费带宽(纯技术上讲,你不关心带宽那是你土豪)。

    于是patch诞生,只传一个userName到指定资源去,表示该请求是一个局部更新,后端仅更新接收到的字段。

    put虽然也是更新资源,但要求前端提供的一定是一个完整的资源对象,理论上说,如果你用了put,但却没有提供完整的UserInfo,那么缺了的那些字段应该被清空。

  • 相关阅读:
    java设计模式0--设计模式简介
    Eclipse常用快捷键与代码模板
    hadoop文件系统与I/O流
    java学习笔记16--I/O流和文件
    hadoop压缩框架
    hadoop中典型Writable类详解
    java学习笔记15--多线程编程基础2
    redis配置密码的方法
    编写的windows程序,崩溃时产生crash dump文件的办法
    windows程序崩溃生成dump文件
  • 原文地址:https://www.cnblogs.com/sunfeiyang/p/12769041.html
Copyright © 2011-2022 走看看