一些基于rest的服务使用不同的资源uri进行更新/获取/删除和创建。如

Create -在某些地方使用/resource(单数)使用POST方法使用/resources(复数) 更新-使用PUT方法使用/resource/123 Get -使用Get方法使用/resource/123

我对这个URI命名约定有点困惑。我们应该用复数还是单数来创建资源?决定的标准应该是什么?


当前回答

请参阅谷歌的API设计指南:资源名称以了解另一种命名资源的方法。

该指南要求集合以复数形式命名。

|--------------------------+---------------+-------------------+---------------+--------------|
| API Service Name         | Collection ID | Resource ID       | Collection ID | Resource ID  |
|--------------------------+---------------+-------------------+---------------+--------------|
| //mail.googleapis.com    | /users        | /name@example.com | /settings     | /customFrom  |
| //storage.googleapis.com | /buckets      | /bucket-id        | /objects      | /object-id   |
|--------------------------+---------------+-------------------+---------------+--------------|

如果你正在思考这个问题,这本书值得一读。

其他回答

使用/resources的前提是它表示“所有”资源。如果执行GET /resources,则可能返回整个集合。通过发布到/resources,您将添加到集合中。

但是,单个资源在/resource上可用。如果执行GET /resource请求,则可能会出错,因为这个请求没有任何意义,而/resource/123则完全有意义。

使用/resource而不是/resources类似于使用文件系统和文件集合,/resource是包含单独的123,456个文件的“目录”。

没有对错之分,你喜欢什么就去做什么。

保持一致就好。

使用任何一个单数:

POST /resource
PUT  /resource/123
GET  /resource/123

或复数:

POST /resources
PUT  /resources/123
GET  /resources/123

以下是Roy Fielding关于“基于网络的软件架构的架构风格和设计”的论文,这句话你可能会感兴趣:

资源是概念上的映射 到一组实体,而不是与中任何特定点的映射对应的实体 时间。

作为一个资源,映射到一组实体,对我来说,使用/product/作为访问一组产品的资源,而不是/products/本身,似乎不符合逻辑。如果需要特定的产品,则访问/products/1/。

作为进一步的参考,这个来源有一些关于资源命名约定的单词和例子:

https://restfulapi.net/resource-naming/

这两种表示都很有用。在相当长的一段时间里,我为了方便而使用单数,屈折变化可能会很困难。根据我在开发严格的单一REST api方面的经验,使用端点的开发人员对结果可能是什么形状缺乏确定性。我现在更倾向于使用最能描述反应形式的术语。

如果您的所有资源都是顶级的,那么您可以使用单一表示。避免变化是一个巨大的胜利。

如果您正在使用任何类型的深度链接来表示关系上的查询,那么使用您的API编写程序的开发人员可以通过使用更严格的约定来获得帮助。

我的习惯是,URI中的每一层深度都描述了与父资源的交互,而完整的URI应该隐式地描述正在检索的内容。

假设我们有以下模型。

interface User {
    <string>id;
    <Friend[]>friends;
    <Manager>user;
}

interface Friend {
    <string>id;
    <User>user;
    ...<<friendship specific props>>
}

如果我需要提供一个资源,允许客户端获得特定用户的特定朋友的管理器,它可能看起来像这样:

GET /用户/ {id} /朋友/ {friendId} /经理

下面是更多的例子:

GET /users - list the user resources in the global users collection POST /users - create a new user in the global users collection GET /users/{id} - retrieve a specific user from the global users collection GET /users/{id}/manager - get the manager of a specific user GET /users/{id}/friends - get the list of friends of a user GET /users/{id}/friends/{friendId} - get a specific friend of a user LINK /users/{id}/friends - add a friend association to this user UNLINK /users/{id}/friends - remove a friend association from this user

注意每个级别是如何映射到一个可以被操作的父级的。为同一个对象使用不同的父对象是违反直觉的。在GET /resource/123处检索资源时,没有指示应该在POST /resources处创建新资源

我也不认为这样做有什么意义,我认为这不是最好的URI设计。作为RESTful服务的用户,无论我访问的是列表还是列表中的特定资源,我都希望列表资源具有相同的名称。无论使用列表资源还是特定资源,都应该使用相同的标识符。