J'ai du mal à déterminer comment concevoir des URL reposantes. Je suis tout à fait en faveur de l'approche reposante consistant à utiliser des URL avec des noms et les verbes ne comprennent pas comment faire cela.
Nous créons un service pour mettre en place une calculatrice financière. La calculatrice prend un tas de paramètres que nous allons télécharger via un fichier CSV. Les cas d'utilisation impliqueraient:
Je suppose que l'approche reposante consisterait à avoir les URL de type suivantes:
/parameters
/parameters/12-23-2009
Vous pouvez réaliser les trois premiers cas d'utilisation avec:
Mais comment faire les 4ème et 5ème cas d'utilisation sans verbe? N'auriez-vous pas besoin d'URL telles que:
/parameters/ID/activate
/parameters/ID/validate
??
Peut-être quelque chose comme:
PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18
{ "active": true }
Principes généraux pour une bonne conception URI:
/resource
ou /resource/
; créer 301 redirections à partir de celle que vous n'utilisez pas(Remarque: je n'ai pas dit "Conception d'URI RESTful"; les adresses URI sont essentiellement opaques dans REST.)
Principes généraux pour le choix de la méthode HTTP:
Principes généraux de la conception de services Web avec HTTP:
201 Created
après la création d'une ressource; la ressource doit exister au moment de l'envoi de la réponse202 Accepted
après une opération réussie ou la création asynchrone d'une ressource400 Bad Request
quand quelqu'un fait une opération sur des données qui sont clairement fausses; pour votre application, cela pourrait être une erreur de validation; réserve généralement 500 pour les exceptions non attrapées401 Unauthorized
lorsque quelqu'un accède à votre API sans fournir d'en-tête Authorization
nécessaire ou lorsque les informations d'identification contenues dans Authorization
ne sont pas valides; n'utilisez pas ce code de réponse si vous n'attendez pas d'informations d'identification via un en-tête Authorization
.403 Forbidden
quand quelqu'un accède à votre API de manière malveillante ou s'il n'est pas autorisé405 Method Not Allowed
quand quelqu'un utilise POST alors qu'il aurait dû utiliser PUT, etc.413 Request Entity Too Large
quand quelqu'un essaie de vous envoyer un fichier trop volumineux418 I'm a teapot
lorsque vous essayez de préparer du café avec une théièreETag
sont utiles lorsque vous pouvez facilement réduire une ressource à une valeur de hachageLast-Modified
devrait vous indiquer qu'il est judicieux de conserver un horodatage de la mise à jour des ressources.Cache-Control
et Expires
doivent recevoir des valeurs sensiblesIf-None-Modified
, If-Modified-Since
)En ce qui concerne votre question spécifique, POST devrait être utilisé pour les points 4 et 5. Ces opérations relèvent de la directive "de type RPC" ci-dessus. Pour le n ° 5, rappelez-vous que POST ne doit pas nécessairement utiliser Content-Type: application/x-www-form-urlencoded
. Cela pourrait tout aussi bien être une charge JSON ou CSV.
Lorsque vous avez besoin d'un nouveau verbe, pensez plutôt à le transformer en nom. Par exemple, transformez "activer" en "activation" et "valider" en "validation".
Mais d'après ce que vous avez écrit, votre application pose des problèmes bien plus importants.
Chaque fois qu'une ressource appelée "paramètre" est proposée, elle devrait envoyer des drapeaux rouges dans l'esprit de chaque membre de l'équipe de projet. 'paramètre' peut s'appliquer littéralement à n'importe quelle ressource; ce n'est pas assez précis.
Que représente exactement un "paramètre"? Probablement un certain nombre de choses différentes, dont chacune devrait avoir une ressource distincte dédiée.
Une autre façon d’en arriver à cela: lorsque vous discutez de votre application avec les utilisateurs finaux (ceux qui en savent probablement très peu sur la programmation), quels sont les mots qu’ils utilisent eux-mêmes de manière répétée?
Ce sont les mots avec lesquels vous devriez concevoir votre application.
Si vous n'avez pas encore eu cette conversion avec des utilisateurs potentiels, arrêtez tout maintenant et n'écrivez pas une autre ligne de code avant de le faire! Ce n’est qu’alors que votre équipe aura une idée de ce qui doit être construit.
Je ne connais rien au logiciel financier, mais si je devais deviner, je dirais que certaines des ressources pourraient être nommées, par exemple, "Rapport", "Paiement", "Virement" et "Monnaie".
Il existe un certain nombre de bons livres sur cette partie du processus de conception de logiciels. Deux que je peux recommander sont Conception gérée par le domaine et Modèles d'analyse .
La conception de vos URL n'a rien à voir avec le fait que votre application soit RESTful ou non. La phrase "URL RESTful" est donc absurde.
Je pense que vous devriez lire un peu plus sur ce que REST est en réalité. REST traite les URL comme étant opaques et, en tant que telles, ne sait pas ce qu’elles contiennent, s’il existe des verbes, des noms ou autre chose. Vous voudrez peut-être quand même concevoir vos URL, mais il s’agit d’une interface utilisateur, pas de REST.
Cela dit, passons à votre question: les deux derniers cas ne sont pas reposants et ne correspondent à aucun type de régime reposant. Ce sont ce que vous pourriez appeler RPC. Si vous êtes sérieux au sujet de REST, vous devrez repenser le fonctionnement de votre application à partir de la base. Soit ça, soit abandonner REST et créer votre application en tant qu'application RPC.
Hmmmm peut-être pas.
L'idée ici est que vous devez tout traiter comme une ressource. Ainsi, lorsqu'un ensemble de paramètres contient une URL à partir de laquelle vous pouvez vous référer, il vous suffit d'ajouter:
GET [parametersurl]/validationresults
POST [paramatersurl]
body: {command:"activate"}
Mais encore une fois, cette chose active est RPC, pas REST.
Les exigences d'activation et de validation sont des situations dans lesquelles vous essayez de modifier l'état d'une ressource. Il n’est pas différent de faire une commande "terminée" ou une autre demande "soumise". Il existe de nombreuses façons de modéliser ce type de changement d'état, mais l'une des méthodes qui fonctionnent souvent consiste à créer des ressources de collection pour les ressources du même état, puis à déplacer la ressource entre les collections afin d'affecter l'état.
par exemple. Créer des ressources telles que,
/ActiveParameters
/ValidatedParameters
Si vous souhaitez activer un ensemble de paramètres, ajoutez-le à la collection ActiveParameters. Vous pouvez soit passer l'ensemble de paramètres en tant que corps d'entité, soit transmettre une URL en tant que paramètre de requête, comme suit:
POST /ActiveParameters?parameter=/Parameters/{Id}
La même chose peut être faite avec/ValidatedParameters. Si les paramètres ne sont pas valides, le serveur peut renvoyer "Demande incorrecte" à la demande pour ajouter les paramètres à la collection de paramètres validés.
Je suggérerais les ressources et méthodes Meta suivantes.
Activer les paramètres et/ou les valider:
> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<
Vérifiez si les paramètres sont actifs et valides:
> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
< 'active': true,
< 'require-valid': true,
< 'valid': {'status': false, 'reason': '...'}
< }
<
Dans un environnement REST, chaque URL est une ressource unique. Quelles sont vos ressources? Une calculatrice financière n'a vraiment pas de ressources évidentes. Vous devez creuser dans ce que vous appelez des paramètres et extraire les ressources. Par exemple, un calendrier d'amortissement pour un prêt peut être une ressource. L'URL du calendrier peut inclure la date de début, la durée (en mois ou en années), la période (lorsque les intérêts sont composés), le taux d'intérêt et le principe initial. Avec toutes ces valeurs, vous avez un calendrier de paiements spécifique:
http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000
Maintenant, je ne sais pas ce que vous calculez, mais votre concept de liste de paramètres ne sonne pas RESTful. Comme quelqu'un d'autre l'a dit, vos exigences ci-dessus sonnent davantage avec XMLRPC. Si vous essayez de rester, vous avez besoin de noms. Les calculs ne sont pas des noms, ce sont des verbes qui agissent sur les noms. Vous devez le retourner pour extraire les noms de vos calculs.
Edit: En effet, l'URI aurait empêché les requêtes GET
de rester idempotentes.
Toutefois, pour la validation, l’utilisation de codes d’état HTTP pour notifier la validité d’une demande (créer un nouveau paramètre ou modifier un paramètre existant) conviendrait au modèle Restful.
Rapportez avec un code de statut 400 Bad Request
si les données soumises sont/sont invalides et que la demande doit être modifiée avant d'être soumise à nouveau ( Codes de statut HTTP/1.1 ).
Cela repose toutefois sur la validation au moment de la soumission, plutôt que de la différer comme dans votre cas d'utilisation. Les autres réponses ont des solutions appropriées à ce scénario.