在 RESTful URL 中使用动词和形容词的替代方法

Posted

技术标签:

【中文标题】在 RESTful URL 中使用动词和形容词的替代方法【英文标题】:Alternatives of using verbs and adjectives in RESTful URL 【发布时间】:2017-04-11 21:16:31 【问题描述】:

我想向我的 REST API 添加操作,以便在不同“商店”之间移动“资源”。

例如,假设我的资源通常通过以下 URL 访问:

/resources
/resources/resourceId

现在假设我想“停用”某些资源,即从概念上将其移动到另一个子文件夹。允许这样做的最直接的方法如下。

    “停用”资源,即使其在 /resources 下不可用。从概念上讲,它将对象“移动”到“/resources/deactivated/”子文件夹:

    POST /resources/resourceId/deactivate   
    

    或者:

    POST /resources/deactivated/resourceId
    

    获取所有停用的对象:

    GET /resources/deactivated      
    

    反转“停用”操作,即从概念上将对象从“/resources/deactivated/”子文件夹移回主文件夹(“/resources”) .

    要么

    POST /resources/resourceId/reactivate    
    

    或者

    POST /resources/deactivated/resourceId/restore     
    

    这个 API 对我来说似乎相当直观。但这似乎违反了我在许多关于 REST API 的最佳实践文章中看到的“首选名词”规则:我使用动词和形容词而不是名词!

请注意,我可能有所有端点的参数,例如GET /resources/deactivated?createdBefore=01022017

我的 REST API 是否有更好的替代方案? IE。更 RESTful,但并非不那么直观?

我可以找到关于该主题的好资源:

Confusion Between Noun vs. Verb in Rest URLs GitHub 对动词的使用(POST /gists/:id/star, DELETE /gists/:id/star):https://***.com/a/19648997/1847482 关于需要寻找“另一种对象类型”的要点:https://***.com/a/2022938/1847482

【问题讨论】:

【参考方案1】:

首先,请记住 REST 代表 Representational State Ttransfer。

这都是关于资源及其状态activatedeactivatemove 等操作都是用新的表示替换资源的当前状态,不需要动词在 URL 中表达此类操作。


例如,要替换资源的状态,您可以在PUT 请求的负载中发送资源的新表示:

PUT /api/resources/[id]/status HTTP/1.1
Host: example.org
Content-Type: application/json

 "status" : "active" 

可以理解为[id]标识的资源状态替换为请求载荷中发送的状态


然后您可以通过以下方式获取具有特定状态的资源:

GET /api/resources?status=active HTTP/1.1
Host: example.org
Accept: application/json

可以理解为给我一个状态为active的所有资源的表示


例如,要将资源移动到另一个文件夹,您可以:

PUT /api/resources/[id]/folder HTTP/1.1
Host: example.org
Content-Type: application/json

 "target" : "draft" 

可以理解为[id]标识的资源所在文件夹替换为请求payload中发送的文件夹

【讨论】:

我喜欢您的回答(已投票),因为它让我更好地理解了 REST 方法。然而,在我的情况下,我不认为简单地更改“状态”属性是可以接受的,因为“获取/资源”不应该返回已停用的属性。 @Alexander 要获取所有资源,您可以请求GET /api/resources。它将返回活动和非活动的。要过滤resources 集合,可以使用status 之类的查询参数。所以GET /api/resources?status=active 将返回活动的,而GET /api/resources?status=inactive 将返回非活动的。您可以假设查询参数的默认值。如果status 被省略,假设您只想要活动的。 我不同意。 'GET /resources' 应该返回所有对象,而不考虑特定属性的值,否则会很混乱。但另一方面,它不应该返回“停用”的,这意味着它不仅仅是一个常规属性。 @Alexander 查看list issues 的 GitHub API:GET /issuesfilter 查询参数可用于指示要返回的问题类型。如果未提供值,则默认使用 assigned 值。 谢谢卡西欧。嗯,深信不疑。他们也用“PUT”在一个要点上加了一颗星。 developer.github.com/v3/gists/#star-a-gist.【参考方案2】:

活动资源与停用资源真的有那么大的不同吗?考虑只拥有一个跟踪activeness 的属性。您可以随时将它们过滤掉,例如

GET /things?active=true

您可以使用 microPUT 仅更改该属性

PUT /things/id/active
false

如果thingdeactivated-thing 在概念上不同,则有两个单独的端点是合理的。我会在他们之间移动使用

POST `/deactivated-things`

    "thing": "/things/12"

POST `/things`

    "deactivated-thing": "/deactivated-things/12"

您应该尽量避免一条具有多重含义的路径。例如,不要这样做:

/resources/id
/resources/deactivated/id

/resources之后的路径段的含义不要重载。

【讨论】:

【参考方案3】:

感谢 Cassio 强调“改变对象状态”的方法。

我自己的完整性回答:

PATCH /resources/resourceId with body "active":false  -- deactivate a resource
PATCH /resources/resourceId with body "active":true  -- restore a resource
GET    /resources                        -- return all 'normal' resources
GET    /resources?includeInactive=true   -- return all resources including the deactivated ones
GET    /resources/resourceId           -- return the resource 

(“GET”检索到的资源将包含“active=true/false”属性)。

似乎是 PATCH 的经典案例:REST API PATCH or PUT

【讨论】:

【参考方案4】:

在 REST 中你从未见过的一件事:

不要将 REST 与网络应用或漂亮的 url 混淆。

例如。当用户登录以编辑他们的帐户时,您会显示

www.example.com/home
www.example.com/account
www.example.com/profile

而不是

// www.example.com/users/id ...
www.example.com/users/433563444335634443356344
www.example.com/users/433563444335634443356344/edit

我认为这是许多开发人员感到困惑的地方。 REST 非常适合 API,但就 Web 应用程序而言,它应该用作表单操作端点或 ajax 的内部 API,但不一定用作漂亮的 url。

【讨论】:

以上是关于在 RESTful URL 中使用动词和形容词的替代方法的主要内容,如果未能解决你的问题,请参考以下文章

通俗易懂的 RESTful API 设计规范

RESTful API 最佳实践

简洁 RESTful API 设计规范!整个人都清爽了!

RESTful 介绍

RESTful API 如何设计

编写高质量代码改善C#程序的157个建议——建议138:事件和委托变量使用动词或形容词短语命名