让我们假设有两个资源Binder
和Doc
有关联关系这意味着Doc
和Binder
在自己的立场。 Doc
可能会或可能不属于Binder
和Binder
可能是空的。
如果我想设计一个REST API,允许用户发送的集合Doc
S, 在单个请求中 ,如下所示:
{
"docs": [
{"doc_number": 1, "binder": 1},
{"doc_number": 5, "binder": 8},
{"doc_number": 6, "binder": 3}
]
}
而在每个文档docs
,
- 如果
doc
存在,那么它分配给Binder
- 如果
doc
不存在,创建它,然后将其指定
我为这个应该怎么实现真的很困惑:
- 用什么HTTP方法?
- 什么响应代码必须返回?
- 这是甚至胜任休息吗?
- 怎样的URI是什么样子?
/binders/docs
? - 处理批量请求,如果一些项目产生一个错误,但其他经历什么。 什么响应代码必须返回? 如果批量操作是原子?
我认为,你可以使用POST或修补的方法来处理这个,因为他们通常设计这一点。
我认为,在这种情况下, POST
和PATCH
是非常相似的,因为你并不真的需要介绍操作的每个元素做。 我要说的是,这取决于代表的格式发送。
的情况下, PUT
是有点不太清楚。 事实上,使用的方法时, PUT
,你应该提供的整个列表。 作为事实上,在请求中提供的表示将在更换名单的资源之一。
你可以有任何关于资源路径两个选项。
在这种情况下,你需要明确地提供文档的链接与您在要求提供的代表性的粘合剂。
下面是该样本路线/docs
。
这种方法的内容可能是方法POST
:
[
{ "doc_number": 1, "binder": 4, (other fields in the case of creation) },
{ "doc_number": 2, "binder": 4, (other fields in the case of creation) },
{ "doc_number": 3, "binder": 5, (other fields in the case of creation) },
(...)
]
此外,您也可以考虑利用子路径来描述文档和粘合剂之间的联系。 关于文档和粘合剂之间的关联暗示目前并不具备被请求的内容中指定。
下面是该样品路线/binder/{binderId}/docs
。 在这种情况下,在发送文档的列表,包括一个方法POST
或PATCH
将附加文档与标识符粘合剂binderId
具有创建的文档,如果它不存在,后。
这种方法的内容可能是方法POST
:
[
{ "doc_number": 1, (other fields in the case of creation) },
{ "doc_number": 2, (other fields in the case of creation) },
{ "doc_number": 3, (other fields in the case of creation) },
(...)
]
关于响应,这是由你来定义响应并返回错误的水平。 我看到两个层次:状态水平(全球)和有效载荷级(细平)。 这也是由你来定义,如果所有对应的请求的插入/更新必须是原子或没有。
在这种情况下,您可以利用HTTP状态。 如果一切顺利的话,你会得到一个状态200
。 如果没有,像另一个状态400
,如果所提供的数据是不正确的(例如粘合剂ID无效)或别的东西。
在这种情况下,一个状态200
将被退回,它是到响应的表示来形容做了什么,并在那里的错误最终可能会发生。 ElasticSearch在其REST API用于批量更新的端点。 这可能给你一些想法在这个级别: http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/bulk.html 。
您也可以实现异步处理来处理所提供的数据。 在这种情况下,HTTP状态回报率将是202
。 客户端需要拉一个额外的资源,看看会发生什么。
结束之前,我也想注意到的OData规范涉及关于与特征命名的导航链接的实体之间的关系问题。 也许你可以看看这个;-)
下面的链接还可以帮助你: https://templth.wordpress.com/2014/12/15/designing-a-web-api/ 。
希望它可以帮助你,蒂埃里
你可能会需要使用POST或补丁,因为它是不可能的更新和创建多个资源的单一请求将被幂等。
这样做PATCH /docs
绝对是一个有效的选项。 您可能会发现使用标准补丁格式棘手您的特定情况。 不知道这件事。
你可以使用200你也可以使用207 -多状态
这可以在一个RESTful的方式来完成。 关键的,在我看来,是有一些资源,旨在接受一组文档更新/创建。
如果您使用补丁的方法,我觉得你的操作应是原子的。 即我不会使用207个状态码,然后在响应机构报告的成功和失败。 如果使用POST操作,则207的做法是可行的。 您必须设计自己的应对机构,其运作成功,它未能连通。 我不知道一个标准之一。
PUT ING
PUT /binders/{id}/docs
创建或更新,并涉及一个单独的文档来粘合剂
例如:
PUT /binders/1/docs HTTP/1.1
{
"docNumber" : 1
}
PATCH ING
PATCH /docs
创建文档,如果不存在,并且它们与粘合剂
例如:
PATCH /docs HTTP/1.1
[
{ "op" : "add", "path" : "/binder/1/docs", "value" : { "doc_number" : 1 } },
{ "op" : "add", "path" : "/binder/8/docs", "value" : { "doc_number" : 8 } },
{ "op" : "add", "path" : "/binder/3/docs", "value" : { "doc_number" : 6 } }
]
我稍后会包括额外的见解,但在此期间,如果你想,看看RFC 5789 , RFC 6902和威廉·杜兰德的请。 不修补像一个白痴博客条目。
在一个项目中,我曾在我们解决了实现的东西,我们称之为“批”的要求这一问题。 我们定义的路径/batch
,我们在下面的格式接受JSON:
[
{
path: '/docs',
method: 'post',
body: {
doc_number: 1,
binder: 1
}
},
{
path: '/docs',
method: 'post',
body: {
doc_number: 5,
binder: 8
}
},
{
path: '/docs',
method: 'post',
body: {
doc_number: 6,
binder: 3
}
},
]
响应有状态代码207(多状态),看起来像这样:
[
{
path: '/docs',
method: 'post',
body: {
doc_number: 1,
binder: 1
}
status: 200
},
{
path: '/docs',
method: 'post',
body: {
error: {
msg: 'A document with doc_number 5 already exists'
...
}
},
status: 409
},
{
path: '/docs',
method: 'post',
body: {
doc_number: 6,
binder: 3
},
status: 200
},
]
你也可以添加在这种结构中头部的支持。 我们实施的东西,事实证明这是变量在批处理请求之间使用,这意味着我们可以使用来自一个请求作为输入到另一个应答。
Facebook和谷歌也有类似的实现:
https://developers.google.com/gmail/api/guides/batch
https://developers.facebook.com/docs/graph-api/making-multiple-requests
当您要创建或更新与同一呼叫我会用POST或PUT根据情况的资源。 如果文件已经存在,你想整个文件是:
- 由您在发送文件替换(含在请求即缺少的属性将被删除,已有的覆盖)?
- 与你在发送文档合并(含在请求即缺少的属性不会被删除,已有的属性将被覆盖)?
如果你想从1备选方案的行为应该使用POST,倘若你想从替代2的行为,你应该使用PUT。
http://restcookbook.com/HTTP%20Methods/put-vs-post/
当人们已经建议你也可以去补丁,但我宁愿保持API的简单,如果不需要,他们不使用额外的动词。