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

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

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


当前回答

使用单数,并利用英语惯例,如:“商业目录”。

很多东西都是这样读的:“书柜”、“狗窝”、“美术馆”、“电影节”、“汽车场”等等。

这方便地从左到右匹配url路径。左边的项目类型。在右侧设置类型。

GET /users真的获取过一组用户吗?不是很经常。它获取一组存根,其中包含一个密钥,也许还有一个用户名。所以它不是/users。它是一个用户索引,或者你可以称之为“用户索引”。为什么不这么叫呢?它是/user/index。由于我们已经命名了set类型,我们可以有多个类型来显示用户的不同投影,而无需求助于查询参数,例如user/phone-list或/user/mail -list。

那么用户300呢?仍然是/user/300。

GET /user/index
GET /user/{id}

POST /user
PUT /user/{id}

DELETE /user/{id}

最后,HTTP对单个请求只能有一个响应。路径总是指一个单数的东西。

其他回答

从API使用者的角度来看,端点应该是可预测的

在理想的情况下……

GET /resources should return a list of resources. GET /resource should return a 400 level status code. GET /resources/id/{resourceId} should return a collection with one resource. GET /resource/id/{resourceId} should return a resource object. POST /resources should batch create resources. POST /resource should create a resource. PUT /resource should update a resource object. PATCH /resource should update a resource by posting only the changed attributes. PATCH /resources should batch update resources posting only the changed attributes. DELETE /resources should delete all resources; just kidding: 400 status code DELETE /resource/id/{resourceId}

这种方法最灵活,功能最丰富,但开发起来也最耗时。因此,如果您很着急(软件开发总是这样),只需命名您的端点资源或复数形式的资源。我更喜欢单数形式,因为它让你可以选择内省和编程计算,因为不是所有的复数形式都以's'结尾。

说了这么多,不管出于什么原因,最常用的实践开发人员选择使用复数形式。这是我最终选择的路线,如果你看看流行的api,如github和twitter,这就是他们所做的。

决定的一些标准可以是:

我的时间限制是什么? 我将允许我的消费者做哪些操作? 请求和结果有效负载是什么样子的? 我是否希望能够在代码中使用反射并解析URI ?

所以这取决于你。无论你做什么都要坚持。

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

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

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

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

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

我不喜欢看到url的{id}部分与子资源重叠,因为id理论上可以是任何东西,而且会有歧义。它混合了不同的概念(标识符和子资源名)。

类似的问题经常出现在枚举常量或文件夹结构中,其中混合了不同的概念(例如,当您有Tigers、Lions和Cheetahs文件夹时,在同一级别上还有一个名为Animals的文件夹——这没有意义,因为其中一个是另一个的子集)。

一般来说,我认为端点的最后一个命名部分如果一次处理单个实体,应该是单数,如果处理一组实体,则应该是复数。

处理单个用户的端点:

GET  /user             -> Not allowed, 400
GET  /user/{id}        -> Returns user with given id
POST /user             -> Creates a new user
PUT  /user/{id}        -> Updates user with given id
DELETE /user/{id}      -> Deletes user with given id

然后有一个单独的资源用于对用户进行查询,通常返回一个列表:

GET /users             -> Lists all users, optionally filtered by way of parameters
GET /users/new?since=x -> Gets all users that are new since a specific time
GET /users/top?max=x   -> Gets top X active users

下面是一些处理特定用户的子资源的例子:

GET /user/{id}/friends -> Returns a list of friends of given user

交个朋友(多对多链接):

PUT /user/{id}/friend/{id}     -> Befriends two users
DELETE /user/{id}/friend/{id}  -> Unfriends two users
GET /user/{id}/friend/{id}     -> Gets status of friendship between two users

永远不会有任何歧义,资源的复数或单数命名都是在暗示用户他们可以期待什么(列表或对象)。对id没有限制,理论上可以让id为new的用户不与(潜在的未来)子资源名重叠。

在这个问题上有很好的讨论点。在我的经验中,命名约定或者更确切地说,没有建立本地标准是许多长夜待命、头痛、危险的重构、可疑的部署、代码审查辩论等等的根本原因。特别是当它决定事情需要改变,因为一开始就没有充分考虑到。

一个实际问题跟踪了关于这个问题的讨论:

https://github.com/kubernetes/kubernetes/issues/18622

在这个问题上看到分歧是很有趣的。

我的观点是,当你考虑用户、帖子、订单、文档等常见实体时,你应该始终将它们视为实际实体,因为这是数据模型的基础。这里不应该混淆语法和模型实体,这将导致其他方面的混淆。然而,一切都是黑白的吗?确实很少这样。环境真的很重要。

当你想获取系统中用户的集合时,例如:

GET /user ->用户实体集合

GET /user/1 ->实体资源user:1 .单击“确定”

说我想要一个实体user的集合和说我想要users的集合都是有效的。

GET /users ->实体用户集合

GET /users/1 ->实体用户资源:1 .单击“确定”

从这里你可以说,从用户集合中,给我user /1。

但如果你分解用户的集合……它是一个实体的集合,其中每个实体都是一个User实体。

您不会说实体是用户,因为单个数据库表通常是用户的单个记录。但是,我们这里讨论的是基于rest的服务,而不是数据库ERM。

但这只适用于名词区分清楚的用户,而且很容易掌握。然而,当一个系统中有多种相互冲突的方法时,事情就会变得非常复杂。

事实上,这两种方法在大多数情况下都是有意义的,除了少数情况下英语就像意大利面条一样。它似乎是一种迫使我们做出许多决定的语言!

简单的事实是,无论你决定什么,你的意图要一致且合乎逻辑。

在我看来,在这里和那里混合是一个糟糕的方法!这会悄悄地引入一些可以完全避免的语义歧义。

看似单一的偏好:

https://www.haproxy.com/blog/using-haproxy-as-an-api-gateway-part-1/

这里也有类似的讨论:

https://softwareengineering.stackexchange.com/questions/245202/what-is-the-argument-for-singular-nouns-in-restful-api-resource-naming

这里最重要的常数是,这似乎确实取决于某种程度的团队/公司文化偏好,根据更大的公司指南中的细节,这两种方式都有许多优点和缺点。谷歌不一定是正确的,因为它是谷歌!这适用于任何指导方针。

不要把你的头埋在沙子里,不要把你的整个理解系统松散地建立在轶事例子和观点上。

你有必要为每件事建立坚实的推理吗?如果它适合你、你的团队和你的客户,并且对新手和经验丰富的开发者(如果你是在团队环境中)有意义,那就很好。

我很惊讶地看到这么多人会追随复数名词的潮流。在实现单数到复数的转换时,是否注意到不规则复数名词?你喜欢疼痛吗?

看到 http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm

不规则复数有很多种,但以下是最常见的:

形成复数形式的

Ends with -fe   Change f to v then Add -s   
    knife   knives 
    life   lives 
    wife   wives
Ends with -f    Change f to v then Add -es  
    half   halves 
    wolf   wolves
    loaf   loaves
Ends with -o    Add -es 
    potato   potatoes
    tomato   tomatoes
    volcano   volcanoes
Ends with -us   Change -us to -i    
    cactus   cacti
    nucleus   nuclei
    focus   foci
Ends with -is   Change -is to -es   
    analysis   analyses
    crisis   crises
    thesis   theses
Ends with -on   Change -on to -a    
    phenomenon   phenomena
    criterion   criteria
ALL KINDS   Change the vowel or Change the word or Add a different ending   
     man   men
     foot   feet
     child   children
     person   people
     tooth   teeth
     mouse   mice
 Unchanging Singular and plural are the same    
     sheep deer fish (sometimes)