您的位置:首页 > 理论基础 > 计算机网络

PUT or POST in RESTful API design

2016-10-06 22:26 337 查看

PUT or POST in RESTful API design

正好在看RESTful的设计方式,感觉之前实现的有问题,所以修改一下。正好也讨论下,以便实现上更标准

主要是考虑到PUT 和POST 的语义上的区别。参考的http文档

http://www.ietf.org/rfc/rfc2616.txt

PUT is idempotent, so if you PUT an object twice, it has no effect

The fundamental difference between the POST and PUT requests is

reflected in the different meaning of the Request-URI. The URI in a

POST request ___identifies the resource that will handle the enclosed

entity___. That resource might be a data-accepting process, a gateway to

some other protocol, or a separate entity that accepts annotations.

In contrast, the URI in a PUT ___request identifies the entity enclosed

with the request___ – the user agent knows what URI is intended and the

server MUST NOT attempt to apply the request to some other resource.

我理解和总结的两点:

put是幂等的操作,即server应该实现和保证操作幂等,无论是故意的操作还是因为网络造成请求重复发送

put对应的URI应该是一个具体的资源实体,并且put请求只应该操作(创建或者修改)这个实体。post则不是,post处理的实体和对应的URI因该是隶属的关系,即实体应该是URI的子集

网上(stackoverflow)上有更具体(暴力)的一种理解:

http://stackoverflow.com/questions/630453/put-vs-post-in-rest/

一旦由你来提供某个具体到资源的URI时,应该用PUT

一旦你不能提供这个具体的资源的URI,而是由服务器来生成时,应该用POST

综上,我觉得PUT对应的操作应该是这样的,创建修改某个URI所对应的具体的资源,而且操作应该有幂等的效果。如果URI不对应某个具体的资源,或者说这个URI甚至应该由server来生成时,应该用POST。

另一个比较好的例子来佐证的是etcd的官方api:

Etcd 源码中 Creat\Update 的实现

func (k *httpKeysAPI) Create(ctx context.Context, key, val string) (*Response, error) {
return k.Set(ctx, key, val, &SetOptions{PrevExist: PrevNoExist})
}

func (k *httpKeysAPI) Update(ctx context.Context, key, val string) (*Response, error) {
return k.Set(ctx, key, val, &SetOptions{PrevExist: PrevExist})
}


k.Set(…) 的实现

func (a *setAction) HTTPRequest(ep url.URL) *http.Request {
u := v2KeysURL(ep, a.Prefix, a.Key)

... ...

req, _ := http.NewRequest("PUT", u.String(), body)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

return req
}


CREAT 正好对应PUT的语义,对应的URI应该指向的是一个具体的资源,而且操作应该是幂等的,不会因为多次提交出现不同结果。(尽管POST也可以保证这几点,但是我觉得PUT更贴合语义)

至于UPDATE的时候该用POST还是PUT?其实这里是有分歧的:

我认为一旦你的URI对应到的是具体的资源,那么这个操作就应该是PUT。leader的理解是POST应该是处理那些部分更新而不是全部更新的操作,因为PUT更像是一种替换的动作。因此使用POST可能更有利于实现。

不过标准终究是给人用的,对于前端开发人员来说,如何更好地接受你所定义的接口至关重要。可能对于具体的http标准所规定的定义来说,习惯的用法更贴近实际一些。

比如让大家把POST换成PUT,虽然代码成本不是特别大,但是对于观念的改变就会需要更大的代价。因此感觉用POST的场景会更多一点。因为标准的规定是一方面,实现又是另一码事了,你完全可以用POST实现一个幂等的操作。

但是还是比较疑惑的一点是 PATCH这个method应该什么时候使用呢?

目前在源码也还没看到有关patch的任何用法= =,但是从语义上理解,补丁(patch)应该是修改的含义,用在update上不会更好么??然而不知为何并不是这样,这里有待进一步的思考.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RESTful http PUT POST 设计