web-dev-qa-db-fra.com

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

Je suis nouveau dans REST et j'ai constaté que, dans certains services RESTful, ils utilisent un URI de ressource différent pour update/get/delete et Create. Tel que

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

Je suis un peu confus à propos de cette convention de nommage URI. Que devrions-nous utiliser pluriel ou singulier pour la création de ressources? Quels devraient être les critères en décidant cela?

464
JPReddy

Le principe d'utilisation de /resources est qu'il représente "toutes" les ressources. Si vous faites un GET /resources, vous retournerez probablement toute la collection. En postant à /resources, vous ajoutez à la collection.

Cependant, les ressources individuelles sont disponibles sur/resource. Si vous faites un GET /resource, vous aurez probablement une erreur, car cette requête n’a aucun sens, alors que /resource/123 a un sens parfait.

Utiliser /resource au lieu de /resources ressemble à ce que vous feriez si vous utilisiez, par exemple, un système de fichiers et une collection de fichiers et que /resource est le "répertoire" avec le chaque fichier 123, 456.

Aucune des deux solutions n'est bonne ou mauvaise, allez avec ce que vous préférez.

248
Will Hartung

Pour moi, il est préférable d'avoir un schéma que vous pouvez mapper directement au code (facile à automatiser), principalement parce que le code est ce qui va se passer des deux côté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) 
547
jla

Je ne vois pas l'intérêt de le faire 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 porte 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.

257
Jan Deinhard

pluriel

  • Simple - toutes les URL commencent par le même préfixe
  • Logical - orders/ obtient une liste d'index des commandes.
  • Standard - Norme la plus largement adoptée suivie par la grande majorité des API publics et privés.

Par exemple:

GET /resources - renvoie une liste d'éléments de ressources

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 uniques:

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

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

Pour les défenseurs du singulier, réfléchissez de la façon suivante: demandez-vous une personne pour une order et attendez-vous une chose ou une liste de choses? Alors, pourquoi vous attendriez-vous à ce qu'un service renvoie une liste d'éléments lorsque vous tapez /order?

61
Eric Knudtson

Singulier

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

par exemple. CustomerAddress over CustomerAddress

Considérez cette ressource connexe.

Ce /order/12/orderdetail/12 est plus 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 devrait avoir un nom singulier logique. Voici le réponse sur les noms de table.

Cartographie de classe

Les cours sont toujours singuliers. Les outils ORM génèrent des tables portant les mêmes noms que les noms de classes. À mesure que de plus en plus d’outils sont utilisés, les noms singuliers deviennent un standard.

En savoir plus sur A REST Le dilemme du développeur d'API

39
Sorter

Alors que la pratique la plus répandue est celle des apis RESTful où l’on utilise des pluriels, 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 individuelles. Spécifiquement si l'élément cible est un objet de valeur (dans le paradigme de conception pilotée par un domaine).

Supposons que chaque ressource a un accessLog qui peut être modélisé comme un objet de valeur, c’est-à-dire pas une entité, donc pas d’ID. Cela pourrait être exprimé par /api/resources/123/accessLog. Les verbes habituels (POST, PUT, DELETE, GET) exprimeraient de manière appropriée l'intention ainsi que le fait que la relation est en réalité un à un.

29
redzedi

Pourquoi ne pas suivre la tendance dominante des noms de table de base de données, où une forme singulière est généralement acceptée? Été là-bas, fait cela - réutilisons-le.

Dilemme de nommage de table: noms singulier vs noms pluriels

20
Slawomir

Je suis surpris de voir que tant de gens sautent dans le train au pluriel. Lorsque vous implémentez des conversions du singulier au pluriel, prenez-vous soin des noms pluriels irréguliers? Aimez-vous la douleur?

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

Il existe plusieurs 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)
14
Stephan Erickson

Du point de vue du consommateur d’API, les ordinateurs d'extrémité doivent être prévisibles

Idéalement...

  1. GET /resources devrait renvoyer une liste de ressources.
  2. GET /resource devrait renvoyer un code d'état de niveau 400.
  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 devrait mettre à jour une ressource en ne publiant que les attributs modifiés.
  9. PATCH /resources devrait mettre à jour par lots les ressources affichant uniquement les attributs modifiés.
  10. DELETE /resources devrait supprimer toutes les ressources; je plaisante: code de statut 400
  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 logiciel), il vous suffit de nommer votre point final resource ou la forme plurielle resources. Je préfère la forme singulière, car elle vous donne la possibilité d’effectuer une introspection et d’évaluer par programmation car toutes les formes plurielles ne se terminent pas par "s".

Cela dit, pour une raison quelconque, les concepteurs de pratiques les plus utilisés ont choisi d’utiliser le pluriel. C’est finalement la voie que j’ai choisie et si vous regardez les apis populaires comme github et Twitter, c’est ce qu’ils 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 le résultat?
  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.

13
cosbor11

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 collecte de clients, mais pour des raisons de simplicité, la partie de la collection est supprimée.

Un autre exemple:

/ équipement/1

Dans ce cas, les équipements ne sont pas la forme plurielle correcte. Donc, le traiter comme une collecte d’équipements et le supprimer pour plus de simplicité le rend compatible avec le cas du client.

5
ivxivx

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

Les pluriels anglais peuvent être très arbitraires et encombrent inutilement le code. S'en tenir à une convention de nommage. Les langages informatiques étaient supposés être basés sur la clarté mathématique, pas sur l’imitation du langage naturel.

5
Guichito

Avec les conventions de dénomination, il est généralement prudent de dire "choisissez-en une et respectez-la", ce qui est logique.

Cependant, après avoir dû expliquer REST à un grand nombre de personnes, représentant les points de terminaison sous la forme chemins sur un système de fichiers, c'est la manière la plus expressive 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 amener que dans les domaines suivants:

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

Et j'aime ça.
Bien que, d’autre part, il s’agisse de votre répertoire, vous pouvez le nommer "une-ressource-ou-plusieurs-ressources" si vous le souhaitez. 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 le devrait; changer de pluriel en singluier, en fonction du nombre de ressources auxquelles vous avez actuellement accès, peut paraître plaisant pour certains, mais ce n'est pas efficace et cela n'a aucun sens hiérarchique système.

Remarque: techniquement, vous pouvez créer des "liens symboliques", de sorte que /resources/123 soit également accessible via /resource/123, mais le premier doit toujours exister!

3
Narf

Un identifiant dans une route doit être considéré comme un index dans une liste, et le nommage doit être poursuivi 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'identifiant dans leurs itinéraires car il n'y en a qu'un, ou un utilisateur n'a jamais accès à plus d'un, de sorte que ce ne sont pas des listes:

GET /dashboard
DELETE /session
POST /login
GET /users/{:id}/profile
UPDATE /users/{:id}/profile
2
TiggerToo

Je sais que la plupart des gens sont entre décider si utiliser le pluriel ou singulier. Le problème qui n'a pas été abordé ici est que le client doit savoir lequel vous utilisez et il est toujours susceptible de se tromper. C'est de là que vient ma suggestion.

Que diriez-vous des deux? Et par là, je veux dire utiliser singulier pour toute votre API, puis créer des itinéraires pour transférer 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 la photo. Personne ne se trompe, effort minimal, et le client aura toujours raison.

2
wynnset

Au moins un aspect de l'utilisation du pluriel pour toutes les méthodes est plus pratique: 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 pour passer de GET à PUT à POST etc.

1
Paulo Merson

Les deux représentations sont utiles. J'avais utilisé singulier pour la commodité pendant un certain temps, l'inflexion peut être difficile. Mon expérience dans le développement d'API strictement singulières REST, les développeurs utilisant le point de terminaison manquent 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 premier niveau, vous pouvez vous en tirer avec des représentations singulières. Éviter les inflexions est une grande victoire.

Si vous faites un type de lien profond pour représenter des requêtes sur des relations, alors les développeurs écrivant contre 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 que l'URI complet doit décrire implicitement ce qui est extrait.

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 permettant à un client d'obtenir le responsable 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 - liste les ressources utilisateur dans la collection globale d'utilisateurs
  • POST /users - crée un nouvel utilisateur dans la collection globale d'utilisateurs
  • GET /users/{id} - récupère un utilisateur spécifique de la collection globale d'utilisateurs
  • GET /users/{id}/manager - récupère le responsable d'un utilisateur spécifique
  • GET /users/{id}/friends - récupère la liste des amis d'un utilisateur
  • GET /users/{id}/friends/{friendId} - obtenir un ami spécifique d'un utilisateur
  • LINK /users/{id}/friends - ajoute une association d'amis à cet utilisateur
  • UNLINK /users/{id}/friends - supprime une association d'amis de cet utilisateur

Remarquez comment chaque niveau correspond à un parent sur lequel il est possible d'agir. Utiliser des parents différents pour le même objet est contre-intuitif. Récupérer une ressource sur GET /resource/123 ne laisse aucune indication que la création d’une nouvelle ressource devrait être effectuée sur POST /resources

1
Steve Buzonas

Que diriez-vous:

/resource/ (pas /resource)

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

Et aussi je pense que la convention de nommage 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".

0
chrisyue

Google Checkout Google Guide de conception de l'API: noms de ressources pour une autre prise en charge des 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   |
|--------------------------+---------------+-------------------+---------------+--------------|
0
Shannon