首页 > 解决方案 > 仅仅为了避免 REST 反模式而为基本相同的逻辑定义两个单独的 API 端点?

问题描述

假设我们在项目管理 SaaS 中的User模型和模型之间存在 M:M 关系。Project自然地,我们有一个将用户映射到项目的数据透视表。如果用户离开或项目经理将该用户从项目中删除,则删除条目。

即使最终结果基本相同(即条目被删除),我想通过定义两个单独的 API 端点来区分这两个操作会更好,如下所示:

用户离开项目

路线DELETE /users/{id}/projects/{id}

UserProjectController@destroy($id)$id项目的行动

项目经理删除用户

路线DELETE /projects/{id}/participants/{id}

ProjectParticipantController@destroy($id)$id用户的动作

我应该忽略 Cruddy by Design 和 RESTful 设计原则,leave() join() remove()而是简单地定义动作并在 URI 中使用动词吗?像这样:

POST /projects/{id}/join

POST /projects/{id}/leave

POST /projects/{id}/participants/{id}/remove

标签: laravelapirestweb-architecture

解决方案


需要考虑的事情:您将如何在网络上进行操作?

即使最终结果基本相同(即条目被删除),我想通过定义两个单独的 API 端点来区分这两个动作会更好

所以在网络上,你很可能有两种不同的表单用于“实现相同的结果”,但这并不一定意味着表单应该针对不同的资源

POST /foo
Content-Type: application/x-www-form-urlencoded

action=UnsubscribeUser&otherArguments=....
POST /foo
Content-Type: application/x-www-form-urlencoded

action=CancelProject&otherArguments=....

“一种资源或两种资源”不是对与错的问题,而是取舍的问题。

POST /projects/{id}/join
POST /projects/{id}/leave
POST /projects/{id}/participants/{id}/remove

这也“很好”;再次,这是一个权衡问题。机器不关心您的标识符在 URI 中是否有动词。

他们确实有点关心读取的标识符是否与写入的标识符相同。请参阅RFC 7234

但是完全合理的说法是,在访问日志或浏览器历史记录中具有语义上重要的 URI 拼写对于我们的长期成功比缓存失效更重要。


请牢记 DELETE(在 HTTP 上下文中)与 SQL 上下文中的 DELETE 不同。我们正在谈论两个具有自己语义的不同名称空间。

HTTP DELETE是通过网络域传输文档。您的处理程序的实现包括 SQL DELETE 的事实完全无关紧要。

相对较少的资源允许使用 DELETE 方法——它的主要用途是远程创作环境,用户对其效果有一定的指导。

可以使用 POST


推荐阅读