假设我的模型是:
用户:
我有一个集合/users/
我希望/users/{id}
而非/users/${nickname}
检索用户,因为在某些更复杂的情况下,可能没有“逻辑唯一约束”。
所以我可以使用的基本JSON有效负载例如:
{
id: 123,
nickname: 'someUserName'
}
这里没什么好看的。
POST / users /
据我所知,用户是一个标识符。它是资源表示的一部分,因此它应该在有效负载(?)中。
如果我想在后端自己生成ID,请使用数据库序列作为示例?
然后我的有效负载变为:
{
nickname: 'someUserName'
}
这是否合适?
该POST的输出应该是什么?没有?只是引用资源位置的标题,包括ID?
获取/ users / id
当我们获取资源时,我们将其内容加载为JSON:
{
id: 123,
nickname: 'someUserName'
}
PUT on / users / id
据我所知,此方法使用的有效负载应该“覆盖”资源内容。如果我们想要部分更新,我们会使用PATCH。
但如果我这样做:
PUT /users/123
{
id: 456,
nickname: 'someUserName'
}
这是否意味着我们想要更新资源的ID?
在URI和有效负载中使用id不是多余的吗?
其实我真的不知道如何处理id
。
我不知道我是否应该在所有POST / PUT / DELETE操作中使用相同的资源表示。
我不知道id是否应该是唯一(?)资源表示的一部分。
但是如果id不是表示的一部分,那么当我列出用户时,使用GET /users/
,如果没有返回id,那么我不知道客户端如何获取用户ID ...
有人能帮助我吗? :)
答案 0 :(得分:5)
首先是 如果您不使用HATEOAS
,则不是REST我希望你理解这一点,我会在最后回到那里。
在/ users / 上发布完全可以在POST有效负载中不使用ID。如果存在ID会出现错误消息,那么开发人员就会明白他们做错了 因此,如果您的用户资源中没有任何其他内容,则只有昵称作为有效负载才是完全有效的
服务器的输出应包括三个重要的事项:
201 Created
)Location: /path/to/resource
)完全有效
您对PUT / PATCH的分析与规范相匹配,新资源应与有效负载相同,这意味着用户希望在不同时更改ID。如果有效负载包含不应更改的值(如ID),则有两种可能:
在这两种情况下都会告知用户您的操作和出错的地方。我更喜欢发送/获得400 Bad Request。如果特权用户可以更改ID,但特定用户不能更改403 403 Forbidden。 还要确保记录您的API行为。您可以在API中省略ID。不要忘记以一致的方式处理POST有效负载中给出的ID!
REST在资源上运行
/ users /是资源集合的示例
/ users / {id}是单个资源的示例
您应该始终在每个响应中使用完全相同的表示。如果由于某种原因,仅提供信息片段更适合添加指向完整资源表示的元数据(链接)。
除了用户的第一个POST请求之外,ID始终存在。
POST意味着资源的未来位置未知,必须由服务器提供。
这也意味着GET / users /应该返回每个资源的ID。
与API一样,返回严格并在请求中宽容。记录您的行为,以便用户可以学习。
如果您实现HATEOAS(超媒体作为应用程序状态引擎),REST的真正美丽就会变为白昼。部分这意味着您应该使用有用的标记/链接组合来表示您的表示。这样客户就不再需要构建网址了。
使用HAL进行用户表示的示例如下:
{
"_links:" {
"self": { "href": "http://yourrest/users/123" }
},
"id": "123"
"nickname": "someUserName"
}
使用HAL的一个很好的总结由Matthew Weier O'Phinney in his blog when he developed a ZF2 REST Module编写(第一个条目是完全免费的,只能解释HAL)。
答案 1 :(得分:0)
我正在解释您的描述,说id
不是资源的一部分,它是资源的唯一标识符。在这种情况下,它不应该是任何操作的有效载荷的一部分。
POST /users
的 {"nickname": "somebody"}
将创建一个新资源,并在Location标头中返回一个URL。该URL可能看起来像/users/123
,但从客户的角度来看,没有理由期待这一点。它可能看起来像/something/else/entirely
。
GET /users/123
会(假设早期POST返回的URL)返回有效负载{"nickname": "somebody"}
。
PUT /users/123
(使用与上面相同的假设)将资源替换为您使用PUT发送的有效负载,例如{"nickname": "somebody else"}
。
如果您希望客户端能够命名资源,那么您还可以PUT /users/123
使用该URL创建新资源。
我知道没有通用的RESTful方法来重命名资源。我认为使用旧URL作为查询部分或正文的一部分的POST是有意义的。
现在,假设我错了,你确实希望id
成为资源本身的一部分。然后每个有效载荷都包含它。但从客户的角度来看,不应假设"id": 123
暗示网址为/users/123
。
最后,所有这些都是从一个相当纯粹的观点来看。将URL视为资源的唯一真实标识符是有价值的,但是破坏该规则并让客户端使用逻辑来创建URL并不是很糟糕。