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风格API中用put还是post做新增操作有什么区别?
- restful,RESTful API 设计,GET/PUT/DELETE/POST
- jax-rs(Java API for RESTful Web Services)实践教程 之二 —— get/post/put/delete/head
- Restful风格API中用put还是post做新增操作有什么区别?
- jax-rs(Java API for RESTful Web Services)实践教程 之二 —— get/post/put/delete/head
- Restful中的get, put 和post
- Node.js实现RESTful api,express or koa?
- warning :OnDestroy or PostNcDestroy in derived class will not be called
- service structure flowchart [mobile to server via HTTP RESTful API and TCP/IP in a map]
- Software Design in a Postmodern Era
- RESTful understand POST VS PUT
- springMVC系列(七)——springMVC实现restful风格开发(post、get、put、delete)
- 简单请假流程中的错误!org.jbpm.api.JbpmException: execution is not in a activity or in a transition
- 创建一个简单的restful wcf, 并且用silverlight做为客户端实现get, post, put,delete
- 【LeetCode】Construct Binary Tree from (Preorder or Postorder) and Inorder Traversal
- 解决 Warning: calling DestroyWindow in CWnd::~CWnd OnDestroy or PostNcDestroy in derived class will not be called
- PUT or POST
- Warning: calling DestroyWindow in CWnd::~CWnd OnDestroy or PostNcDestroy in derived class will not be called
- Design a HashMap class in C++. Implement put, get methods.
- 7.8-7.10 JLL实习日志-DjangoAPI+python+json,post for many records in a time