Convention REST URI - Nom singulier ou pluriel de la ressource lors de sa création

529

Je suis nouveau sur REST et j'ai observé que dans certains services RESTful, ils utilisent différentes URI de ressources pour la mise à jour / obtenir / supprimer et créer. Tel que

  • Créer - en utilisant / resources avec la méthode POST (observez le pluriel) à certains endroits en utilisant / resource (singulier)
  • Mise à jour - utilisation de / resource / 123 avec la méthode PUT
  • Get - Utilisation de / resource / 123 avec la méthode GET

Je suis un peu confus au sujet de cette convention de dénomination d'URI. Que devons-nous utiliser au pluriel ou au singulier pour la création de ressources? Quels devraient être les critères pour décider de cela?

JPReddy
la source
9
Suite à ce sujet, j'ai rassemblé quelques exemples d'API REST célèbres dans un article: inmensosofa.blogspot.com/2011/10/… .
jjmontes
3
La conclusion à laquelle je suis arrivé après avoir lu toutes les réponses ci-dessous: Utilisez toujours le singulier car (a) il est cohérent, (b) il correspond directement aux noms de classe et de table singuliers, (c) certains noms pluriels sont irréguliers (imprévisibles) en anglais
Will Sheppard
Voir cette réponse pour un lien vers les conventions de nommage des tables singulières, et il y a un autre article qui mentionne ce problème exact Dilemme du développeur d'API Rest - merci @Sorter
Will Sheppard

Réponses:

281

La prémisse de l'utilisation /resourcesest qu'elle représente "toutes" les ressources. Si vous le faites GET /resources, vous retournerez probablement la collection entière. En POSTANT sur /resources, vous ajoutez à la collection.

Cependant, les ressources individuelles sont disponibles dans / ressource. Si vous faites cela GET /resource, vous allez probablement faire une erreur, car cette demande n'a aucun sens, alors qu'elle /resource/123est parfaitement logique.

En utilisant au /resourcelieu de /resourcesest similaire à la façon dont vous le feriez si vous travaillez avec, par exemple, un système de fichiers et une collection de fichiers et /resourceest le « répertoire » avec l'individu 123, les 456fichiers qu'il contient .

Aucune des deux façons n'est bonne ou mauvaise, choisissez ce que vous préférez.

Will Hartung
la source
55
Très bonne réponse! Mais les répertoires "par défaut" de Windows ont plusieurs noms. Comme "Program Files", "Users", "Documents", "Videos" etc. J'ai également rencontré beaucoup plus souvent des noms pluriels dans les URL de sites Web.
Dmitry Gonchar
50
la convention de facto que la plupart des gens et des API utilisent est de la garder plurielle à tout moment. Les identifiants spécifient UNE ressource / identifiant de voiture
PositiveGuy
205
"Aucune façon n'est bonne ou mauvaise, allez avec ce que vous aimez le plus.". Ah la célèbre phrase que j'entends si souvent et qui en a marre d'entendre les gens. Les conventions sont importantes et DEVRAIENT être débattues de manière constructive au sein de la communauté, c'est là que de meilleures solutions surgissent et de bonnes pratiques. Lorsque vous utilisez à la fois le pluriel et le singulier pour les noms de ressources dans les URI, cela complique votre code et l'API, car l'utilisateur et le code derrière l'API doivent en tenir compte dans les routes et la logique pour différencier le simple du pluriel, alors que si vous vous en tenez simplement avec le pluriel tout le temps vous n'avez aucun problème.
PositiveGuy
30
@TomaszPluskiewicz Vous avez tout à fait raison de dire que les clients s'en moquent . En tant que développeurs de logiciels, nous devons nous en soucier - et pour cela, je suis d'accord avec le commentaire de la WTF selon lequel les débats constructifs sur la convention sont précieux.
Travis D
12
Alors quelqu'un peut-il simplement mettre une réponse en un mot et la faire accepter, donc je n'ai pas à tout lire (encore).
Ben George
624

Pour moi, il vaut mieux avoir un schéma que vous pouvez mapper directement au code (facile à automatiser), principalement parce que le code sera ce qui va se passer aux deux extrémités.

GET  /orders          <---> orders 
POST /orders          <---> orders.push(data)
GET  /orders/1        <---> orders[1]
PUT  /orders/1        <---> orders[1] = data
GET  /orders/1/lines  <---> orders[1].lines
POST /orders/1/lines  <---> orders[1].lines.push(data) 
jla
la source
22
La difficulté ou la facilité de ceci est due au non-respect d'HATEOS. Peu importe qu'il soit pluriel ou singulier ou autre chose. Vous devez respecter les uri envoyés par le serveur et ne pas "construire" vos uri sur le client. Ensuite, vous avez 0 mappage à faire pour votre code.
richard
7
@richard Le client doit encore faire le mappage. Dans HATEOS, ils devraient correspondre à un nom qui représente la relation (rel) avec la construction de l'URI. Le rel, la méthode (verbe) et le Content-Type constituent alors le support de ressource. Cela n'exclut pas la nécessité d'une bonne conception d'URI. Même si le client peut donner la priorité au nom rel, les développeurs de l'API ont toujours besoin d'une bonne norme lisible par l'homme pour la construction de l'URI.
4
C'est une meilleure réponse à mon avis. Sauf que j'ai toujours préféré utiliser le singulier plutôt que le pluriel. User.getList (), User.getById, User.delete etc.
Eastern Monk
3
J'aime la simplicité. La cartographie a également l'avantage de rendre la documentation et les tests sur les itinéraires incroyablement faciles à écrire.
delos
5
Cela me semble logique. Cependant, nous sommes une boutique axée sur la base de données, ce qui signifie que nous générons du code et des entités api à partir de notre schéma de base de données. Et les normes de base de données ont tendance à préconiser des noms de table singuliers, nous allons donc avec cela, mais toujours dans la même logique que cette réponse.
André C. Andersen
274

Je ne vois pas l'intérêt de faire cela non plus et je pense que ce n'est pas la meilleure conception d'URI. En tant qu'utilisateur d'un service RESTful, je m'attendrais à ce que la ressource de liste ait le même nom, que j'accède à la liste ou à une ressource spécifique «dans» la liste. Vous devez utiliser les mêmes identificateurs, que vous souhaitiez utiliser la ressource de liste ou une ressource spécifique.

Jan Deinhard
la source
69
C'est la meilleure réponse en ce qui me concerne. J'apprécie le fait que les concepteurs d'API apprécient la justesse linguistique de dire «obtenez la ressource # 123», mais c'est un problème de codage supplémentaire lors de l'écriture de clients de l'API ainsi que de la documentation d'aide. (GET / api / people vs GET / api / person / 123? Euuuchh.) .... au lieu de penser à ça comme "get resource # 123", formulez-le dans votre tête comme "get from the collection of resources that correspond à # 123 ".
Warren Rumak
5
Distinguer les ressources plurielles / singulières n'est pas une question d'exactitude linguistique mais d'échelle. / Employés / 12 se lit comme le sous-ensemble de la ressource Employés avec l'ID '12' (cela peut signifier n'importe quoi, par exemple une requête de recherche enregistrée sur des employés récemment licenciés). Si vous lisez ce qui précède comme l'employé avec l'ID «12», comment représenteriez-vous le sous-ensemble? La seule option consiste à rendre l'URI plus complexe en distinguant les collections contenant des objets des objets eux-mêmes (c'est-à-dire au singulier ou au pluriel).
Erik
9
Choisir / employés / 12 pour représenter une requête de recherche sur les employés récemment licenciés (ou tout sous-ensemble) serait une mauvaise conception, je pense. Si vous souhaitez représenter des sous-ensembles de toute nature, je vous suggère de les présenter comme des ressources (avec des noms propres) à part entière.
Jan Deinhard
3
Cela n'a rien à voir avec la compréhensibilité des clients. Il s'agit d'aborder différentes choses avec différentes URL. Et pouvoir répondre à toutes les méthodes HTTP sans être en conflit. Vous pouvez avoir une ressource qui est une collection d'éléments et une ressource qui représente un élément lui-même. Pour tout ce qui m'importe, la ressource des collections pourrait être example.org/166316e2-e1et un élément particulier dans cette collection example.org/20d68348-ccc-001c4200de . Le client ne doit pas construire d'URL (qui ne sont évidemment pas à l'échelle, ce n'est pas RESTful et c'est à cela que servent les types de relation de lien).
Erik
4
Si vous ne pensez pas que les URL arbitraires sont jolies, n'hésitez pas à identifier une ressource de collection avec un nom pluriel et un élément individuel avec un nom singulier. Si vous n'aimez pas les URL anglaises et que votre langue naturelle ne prend pas en charge ce mode de notation singualr / pluriel, utilisez quelque chose d'autre pour le définir dans votre langue préférée. Je suppose que toutes les langues vous permettent de distinguer en quelque sorte '/ the-collection-of- bla / 2321 'contre' bla / 61 'par écrit. Et chacune de ces deux ressources différentes représente des résultats complètement différents lors de l'envoi de GET / PUT / DELETE / POST / PATCH et d'autres.
Erik
77

Pluriel

  • Simple - toutes les URL commencent par le même préfixe
  • Logique - orders/obtient une liste d'index des commandes.
  • Norme - Norme la plus largement adoptée, suivie par l'écrasante majorité des API publiques et privées.

Par exemple:

GET /resources - retourne une liste des éléments de ressource

POST /resources - crée un ou plusieurs éléments de ressource

PUT /resources - met à jour un ou plusieurs éléments de ressource

PATCH /resources - met à jour partiellement un ou plusieurs éléments de ressource

DELETE /resources - supprime tous les éléments de ressource

Et pour les éléments de ressource unique:

GET /resources/:id- renvoie un élément de ressource spécifique basé sur un :idparamètre

POST /resources/:id - crée un élément de ressource avec l'ID spécifié (nécessite une validation)

PUT /resources/:id - met à jour un élément de ressource spécifique

PATCH /resources/:id - met à jour partiellement un élément de ressource spécifique

DELETE /resources/:id - supprime un élément de ressource spécifique

Aux défenseurs du singulier, pensez-y de cette façon: demanderiez-vous à quelqu'un orderune chose et attendez-vous une chose ou une liste de choses? Alors, pourquoi vous attendriez-vous à ce qu'un service retourne une liste de choses lorsque vous tapez /order?

Eric Knudtson
la source
10
Singulier : dans le cas où une partie de votre système est un seul objet (0-1, existe ou non), par exemple utilisateurs / 1 / avatar, vous pouvez utiliser une forme singulière pour étiqueter cet objet unique (par exemple avatar) - exemple plus détaillé ici: stackoverflow .com / a / 38296217/860099 . BTW - très belle réponse :)
Kamil Kiełczewski
Qu'en est-il du mappage avec les noms de classe et de table, qui devraient être singuliers? (voir autre réponse )
Will Sheppard
@WillSheppard - Les noms de classe sont meilleurs au singulier et les noms de table sont meilleurs au pluriel. Par exemple, Orderest un bon nom pour une classe qui traite des instances singulières d'objets se référant à un ordre. OrderListest le nom d'une classe qui traite de plusieurs Orderinstances. Orders Tableest un bon nom pour une table de base de données de nombreuses commandes.
Eric Knudtson
Je veux recevoir / commandes mais je veux seulement / 1
jim smith
@ jim-smith alors pourquoi ne demandez-vous pas / 1 à la collection d'utilisateurs avec GET / users / 1?
Rohmer
49

Singulier

Commodité choses peuvent avoir des noms pluriels irréguliers. Parfois, ils n'en ont pas. Mais les noms singuliers sont toujours là.

par exemple CustomerAddress sur CustomerAddresses

Considérez cette ressource connexe.

C'est /order/12/orderdetail/12plus lisible et logique que/orders/12/orderdetails/4 .

Tables de base de données

Une ressource représente une entité comme une table de base de données. Il doit avoir un nom singulier logique. Voici la réponse sur les noms de table.

Cartographie des classes

Les cours sont toujours singuliers. Les outils ORM génèrent des tables avec les mêmes noms que les noms de classe. Comme de plus en plus d'outils sont utilisés, les noms singuliers deviennent une norme.

En savoir plus sur le dilemme d'un développeur d'API REST

Trieur
la source
39
Les noms singuliers sont toujours là /clothe/12/trouser/34 :)
Gert Arnold
18
@GertArnold le mot clotheest un verbe. Les API de repos respectent généralement les noms lorsqu'ils parlent de ressources et utilisent des verbes lors de la description des actions. La forme singulière est clout, mais est archaïque et serait probablement mieux remplacée par garment.
Steve Buzonas
@SteveBuzonas Et pour les pantalons et les lunettes de soleil?
Koray Tugay
32

Alors que la pratique la plus répandue est l'apis RESTful où les pluriels sont utilisés, par exemple /api/resources/123, il y a un cas spécial où je trouve l'utilisation d'un nom singulier plus approprié / expressif que les noms pluriels. C'est le cas des relations un à un. Plus précisément si l'élément cible est un objet de valeur (dans le paradigme de conception pilotée par domaine).

Supposons que chaque ressource possède un un à un accessLogqui pourrait être modélisé comme un objet de valeur, c'est -à- dire pas une entité, donc pas d'ID. Il pourrait être exprimé comme suit /api/resources/123/accessLog. Les verbes habituels (POST, PUT, DELETE, GET) exprimeraient de manière appropriée l'intention et aussi le fait que la relation est en effet un à un.

redzedi
la source
4
Bien essayé. Mais ce serait mieux comme "accessLogEntries". :-)
Tom Russell
8
@TomRussell pourquoi? Les implications de cela sont importantes. Je comprends pourquoi vous utiliseriez le pluriel même lorsque vous accédez à une ressource par un identifiant, mais pour un plusieurs à un ou un à un, c'est assez trompeur. Considérez une API qui gère les membres du personnel d'une entreprise multi-sites. Chaque membre du personnel travaille à un seul endroit. GET /users/123/locationdevrait récupérer l'emplacement où l'utilisateur travaille. N'est-ce pas GET /users/123/locationsvraiment trompeur en tant que consommateur?
Carrie Kendall
1
@CarrieKendall Je vois votre point. Comme il accessLogest modélisé comme un attribut ou une valeur plutôt que comme une entité, il doit être singulier. Si vous êtes donné à une ingénierie excessive, une entrée de journal serait une entité et vous l'auriez /api/accessLogEntries?resource=123.
Tom Russell
D'accord, bien que, je pense que cela brise la convention de pluraliser toutes choses. C'est délicat. Pour moi, il est important qu'une API soit simple, c'est-à-dire que la documentation devrait compléter une implémentation déjà simple.
Carrie Kendall
Je suis plus un programmeur qu'une personne des systèmes ou des bases de données, j'aime donc une API qui raconte une histoire plutôt que de respecter les conventions. Les implications pour la documentation automatisée sont cependant réelles.
Tom Russell
26

Pourquoi ne pas suivre la tendance répandue des noms de table de base de données, où une forme singulière est généralement acceptée? J'y suis allé, j'ai fait ça - réutilisons.

Dilemme de nom de table: noms singuliers ou pluriels

Slawomir
la source
8
Das Auto est bien meilleur que Die Autos. En outre, les conventions plurielles en anglais ne sont pas cohérentes.
FlavorScape
7
L'espace de noms de ressource est une question de sémantique, pas d'implémentation. Donc, utiliser l'analogie des tables DB, n'est pas très chanceux. De plus, lorsque vous travaillez avec des bases de données, vous manipulez uniquement des tables, bien que vous puissiez bien sûr affecter le contenu (lignes), mais dans REST, il n'y a pas de contrainte pour manipuler directement une seule ressource.
arpadf
3
Je pense que c'est une bonne analogie, mais plus important que de décider d'aller au singulier ou au pluriel est d'être cohérent avec celui que vous choisissez. Vous n'allez pas insérer dans Utilisateurs, puis sélectionner dans Utilisateur. La même règle devrait s'appliquer aux ressources REST - ne les renommez pas en fonction de ce que vous faites.
Todd Menier
3
Ce ne sont pas seulement des noms de table, c'est aussi comparable aux noms de classe dans OO (ma classe s'appellerait Client pas Clients).
bytedev
Dans ce cas, la sémantique est trop importante pour accepter simplement des tendances "déjà définies"
Cattani Simone
19

Je suis surpris de voir que tant de gens sautent dans le train du nom pluriel. Lors de la mise en œuvre de conversions du singulier au pluriel, vous occupez-vous des noms pluriels irréguliers? Aimez-vous la douleur?

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

Il existe de nombreux types de pluriel irrégulier, mais ce sont les plus courants:

Type de nom Former le pluriel Exemple

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)
Stephan Erickson
la source
5
Je ne comprends pas la préoccupation ici. Nous ne sommes pas censés passer du singulier au pluriel par programmation. La plupart des formes plurielles ci-dessus sont bien connues et ne devraient pas être un problème. Si quelqu'un a une mauvaise connaissance de l'anglais, il va orthographier incorrectement n'importe quelle partie de votre variable. En outre, selon votre logique, recommandez-vous également d'utiliser des formulaires singuliers pour référencer des collections dans le code source?
kishor borate
1
Il y a des mots anglais qui sont irréguliers au point où c'est souvent un problème même dans l'Anglosphère et ce sont des termes couramment utilisés tels que index / indexes / indices, vertix / vertixes / vertices, matrix / matrixes / matrices, radius / radiuses / rayons, etc. Je ne vois pas l'intérêt de rendre les chemins REST pluriels de toute façon, car s'ils sont tous toujours singuliers, c'est juste plus évident pour tout le monde.
Damd
@kishorborate, Utiliser le pluriel comme URI est plus sujet aux erreurs, même pour les anglophones natifs. Comme damd l'indique, les pluriels comme index / index / indices introduisent plus de problèmes. Et il y a des noms innombrables. Mélanger les noms indénombrables avec des pluriels est un autre problème. Pourquoi rendre plus difficile pour les programmeurs de passer plus de temps sur ces derniers? Je suggère d'utiliser des singuliers pour tout. S'il existe un / {id}, l'API doit renvoyer un seul enregistrement. S'il n'y a pas un / {id} qui suit, alors l'API doit renvoyer la collection.
Daming Fu
3
@DamingFu Une ressource singulière peut ne pas toujours être associée à un identifiant. par exemple. / user / {id} / nickName En le regardant, ce n'est pas clair, s'il retournera une liste de nickNames ou un seul nickName? Par conséquent, les API sont plus intuitives lorsqu'elles utilisent plusieurs formes. Oui, peu de mots auront des formes plurielles irrégulières. Pour quelqu'un qui lit le pluriel, ce n'est pas un problème. C'est un problème uniquement lors de l'écriture de la signature API. Mais la fréquence de ces mots n'est pas élevée, aussi, trouver le pluriel de n'importe quel mot ne prend pas beaucoup de temps. C'est un compromis que nous devons accepter, pour rendre les API plus intuitives.
kishor borate
15

Du point de vue du consommateur d'API, les points de terminaison doivent être prévisibles afin

Idéalement...

  1. GET /resources devrait renvoyer une liste de ressources.
  2. GET /resource doit renvoyer un code d'état de 400 niveaux.
  3. GET /resources/id/{resourceId} devrait renvoyer une collection avec une ressource.
  4. GET /resource/id/{resourceId} devrait renvoyer un objet ressource.
  5. POST /resources devrait créer des ressources par lots.
  6. POST /resource devrait créer une ressource.
  7. PUT /resource devrait mettre à jour un objet ressource.
  8. PATCH /resource doit mettre à jour une ressource en affichant uniquement les attributs modifiés.
  9. PATCH /resources devrait mettre à jour les ressources par lots affichant uniquement les attributs modifiés.
  10. DELETE /resourcesdevrait supprimer toutes les ressources; je plaisante: 400 code de statut
  11. DELETE /resource/id/{resourceId}

Cette approche est la plus flexible et la plus riche en fonctionnalités, mais aussi la plus longue à développer. Donc, si vous êtes pressé (ce qui est toujours le cas avec le développement de logiciels), nommez simplement votre point de terminaison resourceou le pluriel resources. Je préfère la forme singulière car elle vous donne la possibilité d'introspection et d'évaluation par programme car toutes les formes plurielles ne se terminent pas par 's'.

Cela dit, pour une raison quelconque, le développeur de pratique le plus couramment choisi a choisi d'utiliser le pluriel. C'est finalement la voie que j'ai choisie et si vous regardez les API populaires comme githubet twitter, c'est ce qu'elles font.

Certains critères de décision pourraient être:

  1. Quelles sont mes contraintes de temps?
  2. Quelles opérations vais-je permettre à mes consommateurs de faire?
  3. À quoi ressemblent la demande et la charge utile résultante?
  4. Est-ce que je veux pouvoir utiliser la réflexion et analyser l'URI dans mon code?

C'est à vous de répondre. Quoi que vous fassiez, soyez cohérent.

cosbor11
la source
1
On dirait que le pluriel a été choisi parce que les développeurs semblent supposer que toutes les ressources font intrinsèquement partie d'une collection. Cependant, la "convention acceptée" semble indiquer que cela POST /usersdevrait créer un seul utilisateur, en l'ajoutant à la collection. Je ne suis pas d'accord. POST /usersdevrait créer une liste d'utilisateurs (même s'il s'agit d'une liste de 1), où as POST /userdevrait créer exactement un utilisateur. Je ne vois aucune raison pour laquelle les points de terminaison des ressources au pluriel et au singulier ne peuvent pas coexister. Ils décrivent différents comportements et ne devraient surprendre personne de leur fonction.
écraser
N'y a-t-il pas une convention pour spécifier un identifiant de ressource dans le chemin? Si tel est le cas, il semble être largement négligé. Par exemple, POST users/<id>créerait un nouvel utilisateur.
Tom Russell
1
@TomRussell généralement, le serveur crée l'identifiant, vous ne le savez donc pas encore.
Alex
3
@TomRussell, lorsque le client détermine (une sorte d'ID) lors de la création d'une nouvelle ressource, il est plus courant d'utiliser à la PUT /users/<id>place de POST. POSTa l'interprétation "ajoutez ceci à la collection et déterminez l'id en tant que partie de cela". PUTa l'interprétation «mettre à jour (ou ajouter) cette ressource avec cet identifiant». Voir restcookbook.com/HTTP%20Methods/put-vs-post pour une explication plus longue de ce principe.
Jochem Schulenklopper
Je ne crois pas que la comparaison avec l'API Twitters soit juste car ils utilisent le formulaire Plural pour tous leurs points de terminaison. Ils ne mélangent pas le pluriel et le singulier pour les mêmes éléments.
Andrew T Finnell
7

Mes deux cents: les méthodes qui passent leur temps à passer du pluriel au singulier ou vice-versa sont une perte de cycles CPU. Je suis peut-être de la vieille école, mais à mon époque, les choses s'appelaient pareil. Comment rechercher des méthodes concernant des personnes? Aucune expression régulière ne couvrira à la fois la personne et les personnes sans effets secondaires indésirables.

Les pluriels anglais peuvent être très arbitraires et ils encombrent inutilement le code. Respectez une seule convention de dénomination. Les langages informatiques étaient censés concerner la clarté mathématique, et non l'imitation du langage naturel.

Guichito
la source
2
Cela concerne le code qui essaie de "générer / modifier automatiquement" les points de terminaison (il existe de nombreuses bibliothèques d'opinion qui supposent la pluralité / singularité et tentent de mapper); cependant, cela ne s'applique pas plus aux noms de point de terminaison choisis explicitement qu'à la sélection du bon mot (quelle que soit la façon dont il est pluralisé).
user2864740
6

Je préfère utiliser la forme singulière pour la simplicité et la cohérence.

Par exemple, en considérant l'URL suivante:

/ client / 1

Je traiterai le client comme une collection client, mais pour simplifier, la partie collection est supprimée.

Un autre exemple:

/ équipement / 1

Dans ce cas, les équipements ne sont pas la forme plurielle correcte. Le traiter comme une collection d'équipements et le supprimer pour plus de simplicité le rend cohérent avec le cas client.

ivxivx
la source
2
POST / client sonne comme s'il allait remplacer le seul et unique client. C'est mon plus grand chagrin avec l'utilisation de noms de ressources singuliers.
Andrew T Finnell
2
@ andrew-t-finnell N'est pas POST /customercensé faire la chose même - insérer un seul client?
donmutti
Il insère un seul client dans une collection de clients. POST /customerme lit comme si c'était POST'ing au theclient. Pas une collection de clients. Cependant, je dois admettre que le pluriel ou non pluriel est une préférence. Tant qu'ils ne sont pas mélangés comme l'autre réponse. Ce serait incroyablement déroutant.
Andrew T Finnell
"POSTER au client" n'a pas de sens dans ce cas. POST ne remplace pas, il insère. Peut-être que si c'était POST / customer / 1, je pouvais voir le dilemme, mais même cela n'a pas beaucoup de sens du point de vue REST, car qu'insérez-vous? Ce serait / client / 1 / facture ou / client / 1 / reçu, etc.
damd
5

Un identifiant dans un itinéraire doit être vu de la même manière qu'un index d'une liste, et la dénomination doit procéder en conséquence.

numbers = [1, 2, 3]

numbers            GET /numbers
numbers[1]         GET /numbers/1
numbers.push(4)    POST /numbers
numbers[1] = 23    UPDATE /numbers/1

Mais certaines ressources n'utilisent pas d'identifiants dans leurs itinéraires car il n'y en a qu'un ou un utilisateur n'a jamais accès à plusieurs, donc ce ne sont pas des listes:

GET /dashboard
DELETE /session
POST /login
GET /users/{:id}/profile
UPDATE /users/{:id}/profile
TiggerToo
la source
4

Avec les conventions de dénomination, il est généralement prudent de dire «choisissez-en un et respectez-le», ce qui est logique.

Cependant, après avoir expliqué REST à de nombreuses personnes, représenter les points de terminaison comme des chemins sur un système de fichiers est le moyen le plus expressif de le faire.
Il est sans état (les fichiers existent ou n'existent pas), hiérarchique, simple et familier - vous savez déjà comment accéder aux fichiers statiques, que ce soit localement ou via http.

Et dans ce contexte, les règles linguistiques ne peuvent vous mener que dans la mesure suivante:

Un répertoire peut contenir plusieurs fichiers et / ou sous-répertoires, et son nom doit donc être au pluriel.

Et j'aime ça.
Bien que, d'un autre côté - c'est votre répertoire, vous pouvez le nommer "une-ressource-ou-plusieurs-ressources" si c'est ce que vous voulez. Ce n'est pas vraiment la chose importante.

Ce qui est important, c'est que si vous placez un fichier nommé "123" dans un répertoire nommé "resourceS" (résultant en /resourceS/123), vous ne pouvez pas vous attendre à ce qu'il soit accessible via/resource/123 .

N'essayez pas de le rendre plus intelligent qu'il ne doit l'être - passer du pluriel au singluar en fonction du nombre de ressources auxquelles vous accédez actuellement peut être esthétique pour certains, mais ce n'est pas efficace et cela n'a pas de sens dans un système hiérarchique .

Remarque: Techniquement, vous pouvez créer des "liens symboliques", ce qui /resources/123est également accessible via /resource/123, mais le premier doit encore exister!

Narf
la source
3

Jetez un oeil à Google d » API Guide de conception: les noms des ressources pour une autre prise sur les ressources de nommage.

En bref:

  • Les collections sont nommées avec des pluriels.
  • Les ressources individuelles sont nommées avec une chaîne.
|--------------------------+---------------+-------------------+---------------+--------------|
| API Service Name         | Collection ID | Resource ID       | Collection ID | Resource ID  |
|--------------------------+---------------+-------------------+---------------+--------------|
| //mail.googleapis.com    | /users        | /[email protected] | /settings     | /customFrom  |
| //storage.googleapis.com | /buckets      | /bucket-id        | /objects      | /object-id   |
|--------------------------+---------------+-------------------+---------------+--------------|

Cela vaut la peine d'être lu si vous pensez à ce sujet.

Shannon Matthews
la source
2

L'utilisation du pluriel pour toutes les méthodes est plus pratique au moins sous un aspect: si vous développez et testez une API de ressource à l'aide de Postman (ou d'un outil similaire), vous n'avez pas besoin de modifier l'URI lorsque vous passez de GET à PUT à POST, etc. .

Paulo Merson
la source
1
Ce n'est pas un argument pour moi car Postman propose des collections, vous pouvez donc enregistrer toutes les ressources en tant qu'éléments de collection différents et les tester individuellement. Tout ce que vous faites est de sélectionner la ressource dans la collection, vous n'avez pas à modifier les paramètres / méthodes / etc à chaque fois.
Wirone
1

Les deux représentations sont utiles. J'avais utilisé le singulier pour plus de commodité pendant un certain temps, l'inflexion peut être difficile. Mon expérience dans le développement d'API REST strictement singulières, les développeurs consommant le point de terminaison manquant de certitude quant à la forme du résultat. Je préfère maintenant utiliser le terme qui décrit le mieux la forme de la réponse.

Si toutes vos ressources sont de niveau supérieur, vous pouvez vous en sortir avec des représentations singulières. Éviter l'inflexion est une grande victoire.

Si vous effectuez une sorte de lien profond pour représenter des requêtes sur les relations, les développeurs écrivant sur votre API peuvent être aidés par une convention plus stricte.

Ma convention est que chaque niveau de profondeur dans un URI décrit une interaction avec la ressource parent, et l'URI complet devrait décrire implicitement ce qui est récupéré.

Supposons que nous ayons le modèle suivant.

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

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

Si je devais fournir une ressource qui permet à un client d'obtenir le gestionnaire d'un ami particulier d'un utilisateur particulier, cela pourrait ressembler à ceci:

GET /users/{id}/friends/{friendId}/manager

Voici quelques exemples supplémentaires:

  • GET /users - répertorier les ressources utilisateur dans la collection d'utilisateurs globale
  • POST /users - créer un nouvel utilisateur dans la collection globale d'utilisateurs
  • GET /users/{id} - récupérer un utilisateur spécifique de la collection d'utilisateurs globale
  • GET /users/{id}/manager - obtenir le gestionnaire d'un utilisateur spécifique
  • GET /users/{id}/friends - obtenir la liste des amis d'un utilisateur
  • GET /users/{id}/friends/{friendId} - obtenir un ami spécifique d'un utilisateur
  • LINK /users/{id}/friends - ajouter une association d'amis à cet utilisateur
  • UNLINK /users/{id}/friends - supprimer une association d'amis de cet utilisateur

Remarquez comment chaque niveau correspond à un parent sur lequel il est possible d'agir. L'utilisation de parents différents pour le même objet est contre-intuitive. La récupération d'une ressource à GET /resource/123ne laisse aucune indication que la création d'une nouvelle ressource doit être effectuée àPOST /resources

Steve Buzonas
la source
1

Je sais que la plupart des gens sont entre décider d'utiliser le pluriel ou le singulier. Le problème qui n'a pas été abordé ici est que le client devra savoir lequel vous utilisez, et il est toujours probable qu'il fasse une erreur. C'est de là que vient ma suggestion.

Et les deux? Et par cela, je veux dire utiliser le singulier pour l'ensemble de votre API, puis créer des itinéraires pour transmettre les demandes faites au pluriel au singulier. Par exemple:

GET  /resources     =     GET  /resource
GET  /resources/1   =     GET  /resource/1
POST /resources/1   =     POST /resource/1
...

Vous obtenez l'image. Personne n'a tort, un effort minimal et le client aura toujours raison.

wynnset
la source
1
Si vous effectuez des redirections 302 et que votre cache stocke tout deux fois, vous avez mal configuré votre cache. Le cache n'est pas censé stocker 302 redirections.
wynnset
2
Si votre client utilise /resourceset est toujours redirigé vers /resource, vous l'avez mal fait. Si quelqu'un d'autre utilise votre API, il peut soit utiliser directement l'URL correcte, soit être redirigé (ce qui fonctionne mais est faux) et c'est vous qui avez ouvert la mauvaise voie.
maaartinus
Je ne suis pas sûr de ce que vous entendez par «faux» - c'est très subjectif. Ce n'est pas vraiment faux car cela fonctionne.
wynnset
Cela augmente le coût de maintenance, le coût de la compréhension et la quantité de code requise.
Will Sheppard
1

Je n'aime pas voir la {id}partie des URL se chevaucher avec des sous-ressources, car cela idpourrait théoriquement être n'importe quoi et il y aurait une ambiguïté. Il mélange différents concepts (identifiants et noms de sous-ressources).

Des problèmes similaires sont souvent vus dans des enumconstantes ou dossier structures, où les différents concepts sont mélangés (par exemple, lorsque vous avez des dossiers Tigers, Lionset Cheetahs, puis aussi un dossier appelé Animalsau même niveau - cela n'a aucun sens que l' on est un sous - ensemble de la autre).

En général, je pense que la dernière partie nommée d'un point de terminaison devrait être singulière si elle concerne une seule entité à la fois, et plurielle si elle traite d'une liste d'entités.

Donc, les points de terminaison qui traitent avec un seul utilisateur:

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

Ensuite, il existe une ressource distincte pour effectuer des requêtes sur les utilisateurs, qui retournent généralement une liste:

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

Et voici quelques exemples d'une sous-ressource qui traite avec un utilisateur spécifique:

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

Faites-vous un ami (lien plusieurs à plusieurs):

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

Il n'y a jamais d'ambiguïté, et la dénomination plurielle ou singulière de la ressource est une indication pour l'utilisateur de ce à quoi il peut s'attendre (liste ou objet). Il n'y a pas de restrictions sur ids, ce qui permet théoriquement d'avoir un utilisateur avec l'id newsans chevaucher avec un nom de sous-ressource (futur potentiel).

john16384
la source
1

Utilisez le singulier et profitez de la convention anglaise vue par exemple dans "Business Directory".

Beaucoup de choses lisent de cette façon: "Book Book", "Dog Pack", "Art Gallery", "Film Festival", "Car Lot", etc.

Cela correspond commodément au chemin de l'URL de gauche à droite. Type d'élément à gauche. Définissez le type à droite.

Récupère-t-il GET /usersvraiment un ensemble d'utilisateurs? Pas habituellement. Il récupère un ensemble de talons contenant une clé et peut-être un nom d'utilisateur. Ce n'est donc pas vraiment de /userstoute façon. C'est un index d'utilisateurs, ou un "index d'utilisateurs" si vous voulez. Pourquoi ne pas l'appeler ainsi? C'est un /user/index. Puisque nous avons nommé le type d'ensemble, nous pouvons avoir plusieurs types montrant différentes projections d'un utilisateur sans avoir recours aux paramètres de requête, par exemple user/phone-listou /user/mailing-list.

Et qu'en est-il de l'utilisateur 300? C'est encore /user/300.

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

POST /user
PUT /user/{id}

DELETE /user/{id}

En conclusion, HTTP ne peut avoir qu'une seule réponse à une seule demande. Un chemin fait toujours référence à quelque chose de singulier.

Samuel Danielson
la source
-1

Pour moi, les pluriels manipulent la collection , tandis que les singuliers manipulent l' élément à l' intérieur de cette collection.

La collecte permet les méthodes GET / POST / DELETE

L'élément permet les méthodes GET / PUT / DELETE

Par exemple

POST sur / les étudiants ajouteront un nouvel étudiant à l'école.

SUPPRIMER sur / élèves supprimera tous les élèves de l'école.

SUPPRIMER sur / étudiant / 123 supprimera l'élève 123 de l'école.

Cela peut sembler sans importance, mais certains ingénieurs oublient parfois l'ID. Si l'itinéraire était toujours pluriel et effectuait une SUPPRESSION, vous pourriez accidentellement effacer vos données. Alors que manquer l'identifiant au singulier renverra une route 404 introuvable.

Pour développer davantage l'exemple si l'API était censée exposer plusieurs écoles, alors quelque chose comme

SUPPRIMER dans / école / abc / élèves supprimera tous les élèves de l'école abc.

Choisir le bon mot est parfois un défi en soi, mais j'aime maintenir la pluralité pour la collection. Par exemple cart_itemsou cart/itemsse sent bien. En revanche, la suppression cartsupprime l'objet du panier lui-même et non les articles du panier;).

ruralcoder
la source
Cela ne devrait-il pas être divisé de la manière suivante: / cart et / cart / article (s)? Ensuite, vous pouvez adresser l'ensemble du panier (par exemple avec une suppression) ou des articles individuels?
Rob Grant
@RobertGrant Ne serait-ce pas "/ chariots / articles / 123"? (par exemple, pourquoi "chariot" et non "chariots" est la règle est "toujours pluriel"?)
user2864740
1
Je dirais que si le code de production est archivé qui est capable d'effectuer une suppression des articles du panier de tout le monde, il y a des problèmes plus importants que la convention de dénomination. Le capot probable dont ils se souviendraient d'un 's' sur une pièce d'identité est beaucoup moins.
Andrew T Finnell
Quelqu'un pourrait-il jamais créer un point de terminaison qui supprime simplement une collection entière? Cela me semble extrêmement dangereux, et probablement aussi pourquoi REST ne prend pas vraiment en charge les suppressions par lots. (vous devez envelopper le tableau dans un objet). Si j'avais absolument besoin d'un point de terminaison pour supprimer une collection entière, je m'assurerais que l'URI était très très unique, et certainement pas similaire à POST
cnps
-1

Que diriez-vous:

/resource/(pas /resource)

/resource/ signifie que c'est un dossier contenant quelque chose appelé "ressource", c'est un dossier "resouce".

Et je pense aussi que la convention de dénomination des tables de base de données est la même, par exemple, une table appelée "utilisateur" est une "table utilisateur", elle contient quelque chose appelé "utilisateur".

chrisyue
la source
-2

Je préfère utiliser les deux au pluriel (/resources ) et le singulier ( /resource/{id}) car je pense que cela sépare plus clairement la logique entre travailler sur la collecte de ressources et travailler sur une seule ressource.

En tant qu'effet secondaire important, cela peut également aider à empêcher quelqu'un d'utiliser incorrectement l'API. Par exemple, considérons le cas où un utilisateur essaie à tort d'obtenir une ressource en spécifiant l'ID en tant que paramètre comme ceci:

GET /resources?Id=123

Dans ce cas, lorsque nous utilisons la version plurielle, le serveur ignorera très probablement le paramètre Id et renverra la liste de toutes les ressources. Si l'utilisateur ne fait pas attention, il pensera que l'appel a réussi et utilisera la première ressource de la liste.

En revanche, lors de l'utilisation du singulier:

GET /resource?Id=123

le serveur retournera très probablement une erreur parce que l'ID n'est pas spécifié de la bonne manière, et l'utilisateur devra se rendre compte que quelque chose ne va pas.

pberggreen
la source
1
Pourquoi mélangez-vous des idiomes ici? Vous utilisez la notation URI appropriée dans le premier paragraphe, puis passez aux paramètres de requête? L'utilisation de paramètres de requête pour obtenir une ressource avec un ID de 123 est totalement hors de propos ici.
Andrew T Finnell
C'était clairement une erreur. J'ai mis à jour ma réponse maintenant. Merci de l'avoir remarqué.
pberggreen
Après avoir été rétrogradé à nouveau, j'ai regardé ce que j'ai écrit et j'ai réalisé que le message d'origine était correct. Mon point était exactement que si l'utilisateur fait la mauvaise chose, l'utilisation du pluriel + du singulier donnera en fait un meilleur message d'erreur que l'utilisation du pluriel uniquement.
pberggreen
Je pense toujours que cela prête à confusion. L'idée d'utiliser le pluriel est qu'il s'agit d'une collection. Et le nombre à la fin est un index dans la collection. Et si vous OBTENEZ / ressourcez vous-même? L'utilisation simultanée du pluriel et du singulier est assez déroutante. Dire / ressources / 123 dit: Obtenez ma ressource 123 dans le compartiment des ressources.
Andrew T Finnell