假设我想为人们提供RESTful资源,客户端可以在其中分配ID.
一个人看起来像这样: {"id": <UUID>, "name": "Jimmy"}
现在,客户应该如何保存(或"PUT")呢?
PUT /person/UUID {"id": <UUID>, "name": "Jimmy"} - 现在我们有这个讨厌的重复,我们必须一直验证:身体中的ID是否与路径中的ID匹配?PUT /person/UUID {"name": "Jimmy"}GET /person/UUID 回报 {"id": <UUID>, "name": "Jimmy"}PUT /person/UUID {"name": "Jimmy"}GET /person/UUID 回报 {"name": "Jimmy"}POST由于ID是由客户端生成的,因此似乎不是一个好主意.有哪些常见的模式和解决方法?仅在位置上的ID似乎是最教条正确的方式,但它也使实际实现更难.
Jør*_*ldt 54
使用不同的读/写模型没有任何问题:客户端可以编写一个资源表示,其中服务器可以返回其中添加/计算元素的另一个表示(或者甚至是完全不同的表示 - 任何规范中都没有任何内容,唯一的要求是PUT应该创建或替换资源).
因此,我会选择(2)中的非对称解决方案,并在编写时避免服务器端的"讨厌的重复检查":
PUT /person/UUID {"name": "Jimmy"}
GET /person/UUID returns {"id": <UUID>, "name": "Jimmy"}
Run Code Online (Sandbox Code Playgroud)
Jay*_*ete 21
如果它是一个公共API,你回答时应该保守,但要宽大地接受.
我的意思是,你应该支持1和2.我同意3没有意义.
支持1和2的方法是,如果请求正文中没有提供id,则从url获取id,如果它在请求正文中,则验证它是否与url中的id匹配.如果两者不匹配,则返回400 Bad Request响应.
当返回一个人资源时保守并且总是在json中包含id,即使它在put中是可选的.
这个问题的一个解决方案涉及"超文本作为应用程序状态的引擎"或"HATEOAS"这个有点令人困惑的概念.这意味着REST响应包含要作为超链接执行的可用资源或操作.使用这种方法,它是REST原始概念的一部分,资源的唯一标识符/ ID本身就是超链接.所以,例如,你可以有类似的东西:
GET /person/<UUID> {"person": {"location": "/person/<UUID>", "data": { "name": "Jimmy"}}}
Run Code Online (Sandbox Code Playgroud)
然后,如果要更新该资源,可以执行(伪代码):
updatedPerson = person.data
updatedPerson.name = "Timmy"
PUT(URI: response.resource, data: updatedPerson)
Run Code Online (Sandbox Code Playgroud)
这样做的一个优点是客户端不必了解服务器的用户ID的内部表示.只要客户端有办法发现它们,ID就可能发生变化,甚至URL本身也可能发生变化.例如,在获取人员集合时,您可以返回如下响应:
GET /people
{ "people": [
"/person/1",
"/person/2"
]
}
Run Code Online (Sandbox Code Playgroud)
(当然,您也可以根据应用程序的需要返回每个人的完整人物对象).
使用此方法,您可以根据资源和位置更多地考虑对象,而在ID方面则更少.因此,唯一标识符的内部表示与客户端逻辑分离.这是REST背后的原始动力:通过使用HTTP的功能,创建比以前存在的RPC系统更松散耦合的客户端 - 服务器体系结构.有关HATEOAS的更多信息,请查看Wikipedia文章以及这篇简短的文章.
虽然不同的操作可以有不同的表示形式,但PUT 的一般建议是包含整个有效负载。这意味着它id也应该在那里。否则,您应该使用 PATCH。
话虽如此,我认为 PUT 应该主要用于更新,并且也id应该始终在 URL 中传递。因此,使用 PUT 来更新资源标识符是一个坏主意。id当URL 中的内容与id正文中的内容不同时,这会让我们陷入不希望的情况。
那么,我们如何解决这样的冲突呢?我们基本上有两个选择:
Warning( X-API-Warnetc) 标头。这是我能回答这个问题的最接近的了,因为这个话题总体上是一个意见问题。
在插入中,您不需要在 URL 中添加 id。这样,如果您在 PUT 中发送 ID,您可能会将其解释为 UPDATE 以更改主键。
插入:
PUT /persons/
{"id": 1, "name": "Jimmy"}
HTTP/1.1 201 Created
{"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}
GET /persons/1
HTTP/1.1 200 OK
{"id": 1, "name": "Jimmy", "other_field"="filled_by_server"}
Run Code Online (Sandbox Code Playgroud)
更新
PUT /persons/1
{"id": "2", "name": "Jimmy Jr"} -
HTTP/1.1 200 OK
{"id": "2", "name": "Jimmy Jr", "other_field"="filled_by_server"}
GET /persons/2
HTTP/1.1 200 OK
{"id": "2", "name": "Jimmy Jr", "other_field"="updated_by_server"}
Run Code Online (Sandbox Code Playgroud)
该JSON API使用这个标准,并解决了一些问题,一个链接到新的对象返回插入或更新的对象。某些更新或插入可能包含一些会更改其他字段的业务逻辑
您还将看到可以避免插入和更新后的获取。
小智 5
之前已经有人问过这个问题 - 讨论值得一看:
这是很容易陷入关于什么是“RESTful”、什么不是“RESTful”的争论的问题之一。
对于它的价值,我尝试从一致的资源角度进行思考,而不是在方法之间改变它们的设计。然而,恕我直言,从可用性的角度来看,最重要的是整个 API 保持一致!
仅供参考,这里的答案是错误的。
看:
https://restfulapi.net/rest-api-design-tutorial-with-example/
https://restfulapi.net/rest-put-vs-post/
https://restfulapi.net/http-methods/#patch
放
主要使用 PUT API 来更新现有资源(如果资源不存在,则 API 可能会决定是否创建新资源)。如果 PUT API 创建了新资源,源服务器必须通过 HTTP 响应代码 201(已创建)响应通知用户代理,如果现有资源被修改,则为 200(OK)或 204(无内容)响应代码应该被发送以指示请求的成功完成。
如果请求通过缓存并且请求 URI 标识了一个或多个当前缓存的实体,则这些条目应该被视为过时。对此方法的响应不可缓存。
当您要修改已经是资源集合一部分的单一资源时,请使用 PUT。PUT 完全替换资源。如果请求更新部分资源,请使用 PATCH。
修补
HTTP PATCH 请求是对资源进行部分更新。如果您看到 PUT 请求也修改了资源实体,以便更清楚地说明 – PATCH 方法是部分更新现有资源的正确选择,只有在您完全替换资源时才应使用 PUT。
所以你应该这样使用它:
POST /device-management/devices : Create a new device
PUT /device-management/devices/{id} : Update the device information identified by "id"
PATCH /device-management/devices/{id} : Partial-update the device information identified by "id"
Run Code Online (Sandbox Code Playgroud)
RESTful 实践表明,您在 /{id} 上放置的内容无关紧要——记录的内容应更新为有效负载提供的内容——但 GET /{id} 仍应链接到相同的资源。
换句话说,PUT /3 可能会将有效载荷 id 更新为 4,但 GET /3 仍应链接到相同的有效载荷(并返回 id 设置为 4 的有效载荷)。
如果您决定您的 API 需要在 URI 和有效负载中使用相同的标识符,则您的工作是确保它匹配,但如果您在有效负载中排除了应该完整存在的 id,则一定要使用 PATCH 而不是 PUT . 这就是接受的答案出错的地方。PUT 必须替换整个资源,而补丁可能是部分的。
| 归档时间: |
|
| 查看次数: |
27650 次 |
| 最近记录: |