PUT or POST in RESTful API design

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上不会更好么??然而不知为何并不是这样,这里有待进一步的思考.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值