Question

Je ne parviens pas à 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 œuvre 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:

  1. Télécharger de nouveaux paramètres
  2. Obtenir les derniers paramètres
  3. Obtention des paramètres pour une date d'activité donnée
  4. Activer un jeu de paramètres
  5. Valider un ensemble de paramètres

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:

  1. POST où vous incluez le fichier de paramètres dans la demande de publication
  2. GET de la première URL
  3. GET de la deuxième URL

Mais comment faites-vous 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

??

Était-ce utile?

La solution

Peut-être quelque chose comme:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }

Autres conseils

Principes généraux pour une bonne conception des URI:

  • Ne pas utiliser les paramètres de requête pour modifier l'état
  • N'utilisez pas de chemins d'accès à casse mixte si vous pouvez y remédier. minuscule est le meilleur
  • N'utilisez pas les extensions spécifiques à une implémentation dans vos URI (.php, .py, .pl, etc.)
  • Ne ne tombez pas dans RPC avec vos URI
  • Ne limitez le plus possible votre espace URI
  • Ne gardez les segments de chemin courts
  • Ne préférez / ressource ou / ressource / ; créer 301 redirections à partir de celle que vous n'utilisez pas
  • Utilisez des paramètres de requête pour la sous-sélection d'une ressource; c'est-à-dire pagination, requêtes de recherche
  • Ne déplacez des éléments de l'URI qui doivent figurer dans un en-tête ou un corps HTTP

(Remarque: je n'ai pas dit "Conception d'URI RESTful"; les URI sont essentiellement opaques dans REST.)

Principes généraux pour le choix de la méthode HTTP:

  • N'utilisez jamais GET pour modifier l'état. c’est un excellent moyen pour que Googlebot gâche votre journée
  • Ne pas utiliser PUT, sauf si vous mettez à jour une ressource entière
  • Ne pas utiliser PUT, sauf si vous pouvez légitimement faire un GET sur le même URI
  • Ne pas utiliser POST pour récupérer des informations obsolètes ou susceptibles d'être mises en cache
  • N'effectuez pas d'opération non idempotent avec PUT
  • Faites utiliser GET autant que possible
  • Ne utilisez POST de préférence à PUT en cas de doute
  • Ne utilisez POST chaque fois que vous devez faire quelque chose qui ressemble à RPC
  • Utilisez le PUT pour les classes de ressources plus volumineuses ou hiérarchiques
  • Faites utiliser DELETE plutôt que POST pour supprimer des ressources
  • Utilisez GET pour des opérations telles que les calculs, sauf si votre entrée est volumineuse. Dans ce cas, utilisez POST

Principes généraux de la conception de services Web avec HTTP:

  • Ne mettez pas de métadonnées dans le corps d'une réponse qui devrait figurer dans un en-tête
  • Ne mettez pas les métadonnées dans une ressource distincte, à moins que cela ne crée une surcharge significative
  • Utiliser le code de statut approprié
    • 201 Créé après la création d'une ressource; la ressource doit exister au moment de l'envoi de la réponse
    • 202 Accepté après l'exécution d'une opération ou la création d'une ressource de manière asynchrone
    • 400 requêtes incorrectes lorsqu'une personne effectue une opération sur des données manifestement fictives; pour votre application, cela pourrait être une erreur de validation; réserve généralement 500 pour les exceptions non apprises
    • 401 Non autorisé lorsque quelqu'un accède à votre API sans fournir l'en-tête Autorisation nécessaire ou lorsque les informations d'identification contenues dans Autorisation 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 Autorisation .
    • 403 Interdit lorsqu'une personne accède à votre API de manière malveillante ou si elle n'est pas autorisée
    • 405 Méthode non autorisée lorsque quelqu'un utilise POST alors qu'il aurait dû utiliser PUT, etc.
    • 413 Entité de demande trop grande lorsqu'une personne tente de vous envoyer un fichier trop volumineux
    • 418 Je suis une théière lorsque vous tentez de le faire. préparer du café avec une théière
  • Utilisez des en-têtes de cache chaque fois que vous le pouvez.
      Les en-têtes
    • ETag sont utiles lorsque vous pouvez facilement réduire une ressource à une valeur de hachage
    • Last-Modified doit vous indiquer qu'il est judicieux de conserver un horodatage de la mise à jour des ressources
    • Des valeurs sensibles
    • Cache-Control et Expires doivent être attribuées
  • Faites tout ce que vous pouvez pour honorer les en-têtes de cache d'une requête ( Si-Aucun-Modifié , Si-Modifié-Depuis )
  • Ne utilisez les redirections quand elles ont du sens, mais elles devraient être rares pour un service Web

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 catégorie "RPC-like". ligne directrice ci-dessus. Pour le n ° 5, rappelez-vous que le 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.

Chaque fois qu'il semble que vous ayez besoin d'un nouveau verbe, pensez plutôt à transformer ce verbe en nom. Par exemple, transformez "activer" en "activation" et "valider" en "validation".

Mais d'après ce que vous avez écrit, votre application pose de plus gros problèmes.

Chaque fois qu'une ressource appelée "paramètre" est proposée, elle doit 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 spécifique.

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 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 les utilisateurs potentiels, arrêtez tout maintenant et n'écrivez pas une autre ligne de code avant de l'avoir fait! Alors seulement, votre équipe aura une idée de ce qui doit être construit.

Je ne connais rien aux logiciels financiers, mais si je devais le deviner, je dirais que certaines des ressources pourraient être nommées, par exemple, "Rapport", "Paiement", "Transfert", et "Devise". ;.

Il existe de nombreux livres intéressants sur cette partie du processus de conception de logiciels. Il est recommandé de: Conception centrée sur le domaine et Profils d'analyse .

La conception de vos URL n’a rien à voir avec le fait que votre application soit RESTful ou non. la phrase " RESTful URLS " est donc un non-sens.

Je pense que vous devriez lire davantage sur REST. REST traite les URL comme étant opaques et, en tant que telles, ne sait pas ce qu’elles contiennent, qu’il s’agisse de verbes ou de noms. Vous pouvez toujours vouloir 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.

Hrmmm peut-être pas.

L'idée ici est que vous devez tout traiter comme une ressource. Ainsi, une fois qu'un ensemble de paramètres contient une URL, vous pouvez le référencer, il vous suffit d'ajouter

.

obtenir [parametersurl] / validationresults

post [paramatersurl]

corps: {commande: "activer"}

mais encore une fois, cette chose d'activer 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 "complété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 des ressources du même état, puis à déplacer la ressource entre les collections afin d'affecter l'état.

par exemple. Créez 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 la "requête incorrecte". à la demande pour ajouter les paramètres à la collection de paramètres validés.

Je suggérerais les méthodes et ressources 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 date_début, durée (en mois ou yers), période (lorsque les intérêts sont composés), taux d'intérêt et 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 semble 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, ils sont des verbes qui agissent sur les noms. Vous devez le retourner pour extraire les noms de vos calculs.

Modifier: En effet, l'URI aurait empêché les demandes GET de rester idempotentes.

Toutefois, pour la validation, l’utilisation de codes d’état HTTP pour notifier la validité d’une requête (créer un nouveau paramètre ou modifier un paramètre existant) conviendrait au modèle Restful.

Faites rapport 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 d'état 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 proposent des solutions adaptées à ce scénario.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top