web-dev-qa-db-fra.com

Comment exposer une API de validation de manière RESTful?

Je suis généralement un fan de la conception d'API RESTful, mais je ne sais pas comment appliquer les principes REST pour une API de validation).

Supposons que nous ayons une API pour interroger et mettre à jour les informations de profil d'un utilisateur (nom, email, nom d'utilisateur, mot de passe). Nous avons estimé qu'une fonctionnalité utile à exposer serait la validation, par exemple demander si un nom d'utilisateur donné est valide et disponible.

Quelles sont les ressources dans ce cas? Quels codes de statut HTTP et/ou en-têtes doivent être utilisés?

Pour commencer, j'ai GET /profile/validate qui prend les paramètres de chaîne de requête et renvoie 204 ou 400 si valide ou invalide. Mais validate est clairement un verbe et non un substantif.

63
Aseem Kishore

Le type de chose que vous avez décrit est certainement plus de style RPC dans sa sémantique, mais cela ne signifie pas que vous ne pouvez pas atteindre vos objectifs de manière REST.

Il n'y a pas de VALIDATE verbe HTTP, alors quelle valeur pouvez-vous tirer de la structuration d'une API entière autour de cela? Votre histoire consiste à fournir aux utilisateurs la possibilité de déterminer si un nom d'utilisateur donné est disponible - cela me semble être une simple vérification de la récupération des ressources - GET: /profile/username/... - si le résultat est un 404, le nom est disponible.

Ce que cela met en évidence, c'est que cette validation côté client n'est que cela - côté client. C'est une préoccupation d'interface utilisateur de s'assurer que les données sont validées sur le client avant d'être envoyées au serveur. Un service RESTful ne donne aucun sens, qu'un client ait ou non effectué la validation; il acceptera ou rejettera simplement une demande en fonction de sa propre logique de validation.

REST n'est pas un paradigme qui englobe tout, il décrit uniquement un moyen de structurer les communications client-serveur.

43
Josh E

Nous avons également rencontré le même problème. Notre raisonnement pour que le client s'en remette au serveur pour validation était d'éviter d'avoir des règles incompatibles. Le serveur est tenu de tout valider avant d'agir sur les ressources. Il n'était pas logique de coder ces règles deux fois et de pouvoir les désynchroniser. Par conséquent, nous avons mis au point une stratégie qui semble correspondre à l'idée de REST et en même temps nous permet de demander au serveur d'effectuer la validation.

Notre première étape a été d'implémenter un objet de métadonnées qui peut être demandé à un service de métadonnées (GET /metadata/user). Cet objet de métadonnées est ensuite utilisé pour indiquer au client comment effectuer les validations de base côté client (exigence, type, longueur, etc.). Nous en générons la plupart à partir de notre base de données.

La deuxième partie consiste à ajouter une nouvelle ressource appelée analyse. Ainsi, par exemple, si nous avons un service:

GET /users/100

Nous allons créer une nouvelle ressource appelée:

POST /users/100/analysis

La ressource d'analyse contient non seulement les erreurs de validation qui se sont produites, mais également des informations statistiques qui pourraient être pertinentes si nécessaire. L'une des questions dont nous avons débattu était le verbe à utiliser pour la ressource d'analyse. Nous avons conclu que ce devrait être un POST car l'analyse est en cours de création au moment de la demande. Cependant, il y a eu de solides arguments pour GET également.

J'espère que cela sera utile à d'autres essayant de résoudre ce même problème. Tout commentaire sur cette conception est apprécié.

13
Leslie Hanks

Vous confondez REST avec l'orientation des ressources, il n'y a rien dans REST qui dit que vous ne pouvez pas utiliser de verbes dans les URL. En ce qui concerne la conception d'URL, je choisis généralement ce qui est le plus auto-descriptif, le temps est un nom ou un verbe.

À propos de votre service, ce que je ferais, c'est utiliser la même ressource que vous utilisez pour mettre à jour, mais avec un paramètre de requête de chaîne test, donc quand test=1 l'opération n'est pas terminée, mais vous pouvez l'utiliser pour renvoyer des erreurs de validation.

PATCH /profile?test=1
Content-Type: application/x-www-form-urlencoded

dob=foo

... et la réponse:

HTTP/1.1 400 Bad Request
Content-Type: text/html

<ul class="errors">
  <li data-name="dob">foo is not a valid date.</li>
</ul>
10
Max Toro

C'est génial d'avoir la validation dans l'API REST. Vous avez quand même besoin d'une validation et pourquoi ne pas l'utiliser du côté client. Dans mon cas, j'ai juste une convention dans l'API qu'un error_id spécial représente les erreurs de validation et dans error_details il y a un tableau de messages d'erreur pour chaque feild qui a des erreurs dans ce PUT ou POST. Par exemple:

{
  "error": true,
  "error_id": 20301,
  "error_message": "Validation failed!",
  "error_details": {
    "number": [
      "Number must not be empty"
    ],
    "ean": [
      "Ean must not be empty",
      "Ean is not a valid EAN"
    ]
  }
}

Si vous utilisez la même REST pour les applications Web et mobiles, vous aimerez la possibilité de modifier la validation dans les deux uniquement en mettant à jour l'API. Les mises à jour mobiles spéciales prendraient plus de 24h pour être publiées sur magasins.

Et voici à quoi cela ressemble dans l'application mobile: enter image description here

La réponse du PUT ou POST est utilisée pour afficher les messages d'erreur pour chaque champ. Il s'agit du même appel à partir d'une application Web utilisant React: enter image description here

De cette façon, tous les REST codes de réponse API comme 200, 404 ont leur signification comme ils le devraient. Un appel PUT répond avec 200 même si la validation échoue. Si l'appel passe la validation, la réponse semblera comme ça:

{
  "error": false,
  "item": {
"id": 1,
"created_at": "2016-08-03 13:58:11",
"updated_at": "2016-11-30 08:55:58",
"deleted_at": null,
"name": "Artikel 1",
"number": "1273673813",
"ean": "12345678912222"
  }
}

Vous pouvez apporter des modifications possibles. Maby l'utilise sans error_id. Si vous avez des error_details, bouclez-les et si vous trouvez une clé qui a le même nom qu'un champ, mettez sa valeur en tant que texte d'erreur dans le même champ.

0
Tarik Huber