最近都在尽量用RESTful来做API,所以对一些HTTP中的verb有了新的理解。
其中POST和PUT是混淆比较多的情况,根据以往经验,有这么些理解。
主要参考的是RFC 2616的Section 9.5和Section 9.6
POST的理解
定义中
The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.
这句很明显,是要求服务器把这个请求当做一个资源的下属来处理,这也就是说,POST请求中的URI表示的是一个资源,而请求的内容应该被当做这个资源的一个新下属或则说新的更低一级的资源。
从RESTful来讲,用POST的时候,往往会使用server/resources
作为URI,而不指定resource的ID,也就是说,经常用来创建资源,比如创建一个用户,一个文章。
并且返回的状态码,可以是表示错误的400以上,或者是表示创建成功的201,并且需要带Location的header来表示新创建的URI,一般为server/resources/ID
,可以通过GET动词来获取这个URI的详细信息。
另外,POST返回还可以是200或者204,取决于返回的body里面是否有内容,而这个是在创建的资源无法被URI表示出来的情况。
有可能是创建了一个抽象的东西或者现有的URI无法指示,比如登录时,使用POST server/sessions
,来开始一个会话,当登录成功时,服务器不能把这个session信息用URI表示出来,但是根据服务器实现不同,可能会有不同描述,此时会返回204(No Content,没有具体信息),或者200(有具体信息,比如之后用到的token)。
但是RESTful中一般不会使用这种登录方式,而会使用OAuth的方式。
PUT的理解
The PUT method requests that the enclosed entity be stored under the supplied Request-URI.
这句很重要,说明了PUT的所有操作,就是在指定的URI下进行,不会跑去其他地方做修改。
If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server.
也就说,指定的URI如果已经纯在一个资源了,那么就应该当做去修改。
If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
在不存在指定资源的时候,服务器可以在这个URI底下去创建一个资源。
也就说,指定server/resources
为URI的话,如果能够被当做是一个资源的话,那么就会在这个位置创建一个资源,并且以后就是使用这个URI来访问。
在RESTful中,用PUT来创建资源的情况就比较少了,因为创建时并不会去指定resource的ID,但是server/resources又不是一个有效的资源,所以RESTful中一般会使用POST去创建资源而不是PUT。
除非,这个资源不是数据库中需要自增的资源,比如文件,而server/file/ID又正好是有效的服务器URI,那么就可以使用PUT来上传文件了。
这种情况下,POST反而不适用了,因为POST会在这个URI下创建文件,比如server/file/ID/subID,这样意思就不一样了。
又或者,给某个resource指定一个资源,比如,给user指定一个头像文件,使用server/user/ID/avatar
做为URI,那么你可以使用PUT。同样的,如果你的avatar只有一个,那么你应该使用PUT,而avatar可以使用多个,而且server/user/ID/avatar/subID是一个可用URI,而subID又不是可以确定的,那么上传时应该使用POST。
总结
在RESTful中,可以这样说,
PUT主要负责修改指定位置的资源,只要你的URI是一个服务器能够理解的URI。也就是说,只要是指定了位置,那么就可以去修改。
而POST主要负责创建某种类型的资源,不需要指定资源的位置,而是由服务器自己去分配资源。