在 REST API 中实施业务逻辑时,事实上/传统的做法是什么?使用了哪些 HTTP 状态代码?
例如,假设我有一个 Player 实体和一个 Team 实体。一个团队可以有任意数量的玩家。
假设我的业务逻辑(当前)阻止删除团队,直到首先从团队中明确删除所有玩家。
如果您执行
DELETE http://api.foo.com/teams/15
并且它仍然有与之关联的玩家,您会返回 HTTP 409(冲突)还是 HTTP 412(前提条件失败) )? 412 似乎更合乎逻辑,因为我更喜欢使用 409 来指示乐观锁定条件。
或者也许 - 业务逻辑条件是否应该在 REST API 中强制执行?也就是说,如果有人执行
DELETE http://api.foo.com/teams/15
,
难道不应该删除所有玩家,然后自动删除团队吗?允许 DELETE 执行是否更传统,因为 REST API 可以被视为比 UI 界面稍微“低级”或更“原始”?
最后,资源 URI 中的查询参数怎么样:
DELETE http://api.foo.com/teams/15?force=true
表示“是的,我知道这不会”不允许球员仍在球队中,但无论如何都要这样做”。
这里的想法是,删除团队可能是一项重量级操作,会产生重大影响,并且只有在最终用户确实确定他们想要这样做时才需要这样做。
换句话说,您需要进行多少手动操作(使用“您确定吗?”错误代码),还是只是在不进行任何检查的情况下执行它?我不太确定是否应该仅在 UI 或 REST API 或两者中强制执行此操作。今天大多数人如何解决这个问题?
What is the de-facto/conventional practice when enforcing business logic in a REST API and what HTTP Status Codes are used?
For example, lets say that I have a Player entity and a Team entity. A Team can have any number of players.
Let's say that my business logic (currently) prevents a Team from being deleted until all of the Players have been explicitly removed from the Team first.
If you execute a
DELETE http://api.foo.com/teams/15
and it still has Players associated with it, would you return an HTTP 409 (Conflict) or an HTTP 412 (Precondition Failed)? 412 seems more logical because I prefer to use 409 for indicating optimistic locking conditions.
Or perhaps - should that business logic condition even be enforced at all in a REST API? That is, if someone executes
DELETE http://api.foo.com/teams/15
shouldn't that just remove all Players and then delete the Team automatically? Is it more conventional to allow the DELETE to execute as the REST API can be perceived as a little 'lower level' or more 'raw' than UI interfaces?
Finally, what about a query param to in the Resource URI:
DELETE http://api.foo.com/teams/15?force=true
which indicates, "Yes, I know that this wouldn't be allowed with players still on the team, but do it anyway".
The idea here is that deleting a Team can be a heavyweight operation with significant repercussions and you only want to do it if the end-user is really sure they want to.
In other words, how much hand-holding do you do (employing 'are you sure?' error codes) or do you just execute it without any check? I'm not quite sure if this should be enforced only in the UI or in the REST API or both. How do most people solve this today?
发布评论
评论(3)
客户试图做一些出于商业原因而不是有效请求的事情。因此,我会使用 400。如果您想传达其他详细信息,请使用 ReasonPhrase/实体主体。
The client tried to do something that for business reasons was not a valid request. Therefore, I would use 400. Use the ReasonPhrase/entity body if you want to communicate additional details.
在这种情况下,412 是不正确的,因为这是基于请求标头字段的评估(请参阅 此问题了解何时使用 HTTP 412)。这里正确的状态代码是 403 Forbidden——即请求已被理解,但拒绝执行,授权也无济于事。您可以在响应正文中向客户端提供更多详细信息。
至于是否应该实现业务逻辑,这完全取决于您。您甚至可以选择基于 ACL 实施此类检查 - 例如,某些用户只能在删除所有玩家后才能删除团队,而管理员无论如何都可以删除团队。非管理员用户对包含玩家的团队发出 DELETE 请求现在应返回 401 Unauthorized(即,针对这些凭据的操作被拒绝)。管理员用户将获得 200。
编辑:一如既往,更多信息位于 RFC 2616。
412 would be incorrect in this case since this is based on evaluation of request-header fields (see this question for when to use HTTP 412). The correct status code here would be 403 Forbidden — i.e. request understood, but refusing to do it, and authorization will not help. You can provide more details to the client in the response body.
As far as whether the business logic should even be implemented, that's entirely up to you. You may even choose to implement that sort of check based on ACL — for example, certain users are only able to DELETE the team once all players have been deleted, and admins can DELETE teams regardless. A non-admin user making a DELETE request for a team with players should now return a 401 Unauthorized (i.e. the action was refused for those credentials). Admin users would get a 200.
EDIT: More information, as always, in RFC 2616.
我曾经工作过的情况,REST 服务托管在 Lotus Notes 上,如果我们需要从 Lotus Notes 中删除任何条目,我们强制设置“确认/强制”true 参数,只是为了确保调用者(UI/REST 客户端)知道删除。如果您的服务是 REST 服务,我认为在 UI 级别还不够,我们还需要在 REST URL 中具有相同的约束。
我没有遇到像你提到的任何场景(删除团队应该删除玩家),但在这种特殊情况下我更倾向于 412 代码。
The cases I have worked where REST service hosted on lotus notes, if we need to delete any entry from lotus notes, we mandated to set 'confirm/force' true parameter, just to make sure invoker (UI/REST Client) are aware of deletion. If your service is REST service, I think having at UI level is not quite enough, we need to have same constraint in REST URL also.
I haven't encountered any scenario like you mentioned (delete team should delete player), but I would lean more towards 412 code in this particular case.