160 votes

Appel d'un Serveur-côté de la Méthode sur une Ressource dans une bonne Voie

Gardez à l'esprit que j'ai une compréhension rudimentaire de REPOS. Disons que j'ai cette URL:

http://api.animals.com/v1/dogs/1/

Et maintenant, je veux faire sur le serveur, faire le chien qui aboie. Seul le serveur sait comment faire cela. Disons que je veux le faire tourner sur une tâche CRON qui fait le chien qui aboie toutes les 10 minutes pour le reste de l'éternité. Ce n'est que l'appel? Je voudrais faire ceci:

Demande d'URL:

ACTION http://api.animals.com/v1/dogs/1/

Dans le corps de la requête:

{"action":"bark"}

Avant de vous mettre en colère contre moi pour faire ma propre méthode HTTP, m'aider et me donner une meilleure idée sur comment je dois appeler un serveur-côté de la méthode dans un cadre Reposant. :)

MODIFIER POUR LA CLARIFICATION

Plus de clarifications autour de ce que le "écorce" méthode. Voici quelques options qui peuvent entraîner à la structure différente des appels d'API:

  1. l'écorce envoie juste un mail pour chien.email et dossiers rien.
  2. l'écorce envoie un mail pour chien.e-mail et les incréments de chien.barkCount par 1.
  3. l'écorce de crée un nouveau "écorce" enregistrement avec de l'écorce.horodatage de l'enregistrement lorsque l'écorce s'est produite. Il a également incréments de chien.barkCount par 1.
  4. l'écorce s'exécute une commande système pour tirer la dernière version du chien de code vers le bas à partir de Github. Il envoie ensuite un message de texte pour chien.propriétaire de leur dire que le nouveau chien de code de production.

6voto

Jordan Points 1202

J'ai répondu plus tôt, mais cette réponse contredit mon ancienne réponse et suit une stratégie bien différente pour arriver à une solution. Il montre comment la requête HTTP est construite à partir de concepts qui définissent le REPOS et HTTP. Il utilise également PATCH au lieu de POST ou PUT.

Il va à travers le RESTE les contraintes, puis les éléments de HTTP, puis une solution possible.

RESTE

Le REPOS est un ensemble de contraintes destinées à être appliquées à un hypermédia distribués système afin de le rendre évolutif. Même pour lui donner un sens dans le contexte de contrôler à distance une action, vous devez penser de contrôler à distance une action en tant que partie d'un système hypermédia distribués -- une partie d'un système de découvrir, voir et modifier interconnectés de l'information. Si c'est plus d'ennuis que cela vaut la peine, alors il n'est probablement pas bon pour essayer de rendre tout repos. Si vous voulez juste un "panneau de configuration" type GUI sur le client qui peut déclencher des actions sur le serveur via le port 80, alors vous voudrez probablement une simple interface RPC comme JSON-RPC via des requêtes/réponses HTTP ou un WebSocket.

Mais le RESTE est d'une façon fascinante de la pensée et de l'exemple de la question se trouve être facile pour modèle avec une interface RESTful, prenons donc le défi pour le fun et pour l'éducation.

Le REPOS est définie par quatre contraintes d'interface:

l'identification des ressources; la manipulation des ressources à travers des représentations; auto-descriptif des messages; et, de l'hypermédia comme le moteur de l'état de l'application.

Vous vous demandez comment vous pouvez définir une interface, la satisfaction de ces contraintes, par l'intermédiaire de laquelle un ordinateur indique un autre ordinateur pour faire un aboiement de chien. Plus précisément, vous voulez que votre interface HTTP, et vous ne voulez pas pour jeter les caractéristiques qui font de HTTP Reposante lorsqu'il est utilisé comme prévu.

Commençons avec la première contrainte: identification de ressources.

Toute information qui peut être nommé peut être une ressource: un document ou une image, un temps de service (par exemple, "aujourd'hui, la météo à Los Angeles"), une collection d'autres ressources, un non-objet virtuel (par exemple, une personne), et ainsi de suite.

Si un chien est une ressource. Il doit être identifié.

Plus précisément, une ressource R est un temporellement variable appartenance à la fonction MR(t), qui pour le temps t correspond à un ensemble d'entités, ou des valeurs, qui sont l'équivalent. Les valeurs peuvent être des ressources représentations et/ou des identifiants de ressource.

Vous modèle un chien en prenant une série d'identificateurs et des représentations, et en disant qu'ils sont tous liés les uns avec les autres à un moment donné. Pour l'instant, nous allons utiliser l'identificateur de chien "#1". Ce qui nous amène à la deuxième et à la troisième contraintes: les contraintes de ressources de représentation et d'auto-description.

RESTE des composants d'effectuer des actions sur une ressource à l'aide d'une représentation à la capture de l'actuel ou prévu de l'état de la ressource et de transfert de cette représentation entre les composants. Une représentation est une séquence d'octets, en plus de la représentation de métadonnées pour décrire ces octets.

Voici une séquence d'octets capture de l'état prévu de le chien, c'est à dire la représentation que nous souhaitons être associés à l'identifiant de chien "#1" (notez qu'il ne représente qu'une partie de l'état car il ne concerne pas le nom du chien, de la santé, ou même au-delà écorces):

Il a été aboyer toutes les 10 minutes depuis le temps que ce changement d'état a été effectuée, et peut se poursuivre indéfiniment.

Il est censé être attachés à des métadonnées qui les décrivent. Ces métadonnées peuvent être utiles:

C'est une anglaise déclaration. Il ne décrit qu'une partie de l'état prévu. S'il est reçu plusieurs fois, seulement le premier à avoir un effet.

Enfin, regardons la quatrième contrainte: HATEOAS.

RESTE ... vues d'une application comme une structure cohérente d'information et de contrôle alternatives à travers laquelle l'utilisateur peut effectuer une tâche donnée. Par exemple, à la recherche d'un mot dans un dictionnaire en ligne est une application, est en tournée à travers un musée virtuel, ou l'examen d'un ensemble de notes de cours à étudier pour un examen. ... La prochaine contrôle de l'état de l'application réside dans la représentation de la première ressource demandée, de sorte que l'obtention de cette première représentation est une priorité. ... Le modèle d'application est donc un moteur qui se déplace d'un état à l'autre, en examinant et en choisissant parmi les alternatives les transitions de l'état dans l'ensemble des représentations.

Dans une interface RESTful, le client reçoit une ressource de représentation afin de comprendre comment il devrait recevoir ou envoyer une représentation. Il doit y avoir une représentation quelque part dans l'application à partir de laquelle le client peut comprendre comment envoyer ou recevoir de toutes les représentations, il devrait être en mesure de recevoir ou d'envoyer, même si elle suit une chaîne de représentations pour arriver à cette information. Cela semble assez simple:

Le client demande une représentation d'une ressource identifiée comme la page d'accueil; en réponse, il obtient une représentation qui contient un identifiant de chaque chien le client pourrait vouloir. Le client extraits d'un identifiant et demande le service de la façon dont il peut interagir avec l'identifiés chien, et le service dit le client peut envoyer un anglais description de la partie de l'état du chien. Ensuite, le client envoie une telle déclaration et reçoit un message de réussite ou d'un message d'erreur.

HTTP

HTTP implémente RESTE contraintes comme suit:

identification de ressources: URI

ressources de la représentation: entité-corps

l'auto-description: la méthode ou le code d'état, en-têtes, et peut-être de parties du corps d'entité (par exemple, l'URI de schéma XML)

HATEOAS: les liens hypertexte

Vous avez décidé sur http://api.animals.com/v1/dogs/1 comme l'URI. Supposons que le client a obtenu ce à partir d'une page sur le site.

Nous allons utiliser cette entité-corps (la valeur de next est un timestamp; une valeur de 0 signifie "lorsque cette demande est reçue'):

{"barks": {"next": 0, "frequency": 10}}

Maintenant nous avons besoin d'une méthode. PATCH correspond à la "partie de l'état" description nous avons décidé de:

Le PATCH demandes de méthode que d'un ensemble de changements décrits dans la demande de l'entité, être appliquée à la ressource identifiée par l'URI de Demande.

Et certains en-têtes:

Pour indiquer la langue du corps d'entité: Content-Type: application/json

Assurez-vous que cela n'arrive qu'une fois: If-Unmodified-Since: <date/time this was first sent>

Et nous avons une demande:

PATCH /v1/dogs/1/ HTTP/1.1
Host: api.animals.com
Content-Type: application/json
If-Unmodified-Since: <date/time this was first sent>
[other headers]

{"barks": {"next": 0, "frequency": 10}}

En cas de succès, le client doit recevoir un 204 code d'état de réponse, ou un 205 si la représentation de l' /v1/dogs/1/ a été modifiée pour refléter la nouvelle aboiements de l'annexe.

En cas d'échec, il devrait recevoir un 403 et un précieux message pourquoi.

Il n'est pas essentiel RESTE pour le service pour tenir compte de l'écorce dans le calendrier d'une représentation en réponse à l' GET /v1/dogs/1/, mais ça aurait plus de sens si une représentation JSON inclus ce:

"barks": {
    "previous": [x_1, x_2, ..., x_n],
    "next": x_n,
    "frequency": 10
}

Traiter la tâche cron comme un détail d'implémentation que le serveur cache de l'interface. C'est la beauté d'une interface générique. Le client ne doit pas savoir ce que fait le serveur en coulisses, il se soucie est que le service comprend et répond à la demande des changements d'état.

4voto

Raymond Hettinger Points 50330

La plupart des gens utilisent POST à cet effet. Il est approprié pour la réalisation de "tout dangereux ou nonidempotent opération, lorsque aucune autre méthode HTTP semble approprié".

Des api comme XMLRPC utilisation POST pour déclencher les actions qui peuvent exécuter du code arbitraire. L ' "action" est inclus dans le message de données:

POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: betty.userland.com
Content-Type: text/xml
Content-length: 181

<?xml version="1.0"?>
<methodCall>
   <methodName>examples.getStateName</methodName>
   <params>
      <param>
         <value><i4>41</i4></value>
         </param>
      </params>
   </methodCall>

Le RPC est l'exemple est donné pour montrer que la POSTE est le choix ordinaire des verbes HTTP pour le serveur-côté des méthodes. Voici Roy Fielding réflexions sur le POST - il dit à peu près c'est Reposant à utiliser les méthodes du protocole HTTP comme spécifié.

Notez que RPC lui-même n'est pas très Reposant car il n'est pas orientées vers les ressources. Mais si vous avez besoin d'apatridie, la mise en cache, ou en superposition, il n'est pas difficile de faire des transformations. Voir http://blog.perfectapi.com/2012/opinionated-rpc-apis-vs-restful-apis/ pour un exemple.

2voto

Jacob Stevens Points 302

POST est la méthode HTTP conçus pour

Fournir un bloc de données...à un processus de traitement des données

Côté serveur, les méthodes de manipulation non-CRUD-mappé actions est ce que Roy Fielding prévu avec du REPOS, de sorte que vous êtes bien là-bas, et c'est pourquoi, POST a été faite pour être non-idempotent. POST sera poignée plus l'affichage de données côté serveur, les méthodes de traitement de l'information.

Cela dit, dans votre chien aboie scénario, si vous voulez un serveur-côté de l'écorce doit être réalisée toutes les 10 minutes, mais pour une raison quelconque besoin de le déclencheur provenir d'un client, PUT permettrait de mieux, en raison de son idempotence. Eh bien, strictement par ce scénario il n'y a pas de risque apparent de multiples requêtes POST à l'origine de votre chien à miauler à la place, mais de toute façon c'est le but des deux méthodes similaires. Ma réponse à une semblable question peut être utile pour vous.

1voto

Nicholas Points 2862

Les révisions antérieures de certaines réponses suggère de les utiliser RPC. Vous n'avez pas besoin de regarder à la RPC comme il est parfaitement possible de faire ce que vous voulez tout en respectant le RESTE les contraintes.

Tout d'abord, ne pas mettre des paramètres dans l'URL. L'URL définit ce que vous êtes d'appliquer l'action, et les paramètres de la requête sont une partie de l'URL. Il devrait être considéré exclusivement comme un substantif. http://api.animals.com/v1/dogs/1/?action=bark est une ressource différente - un autre nom - http://api.animals.com/v1/dogs/1/. [n.b. Le demandeur a retiré l' ?action=bark de l'URI de la question.] Par exemple, comparer http://api.animals.com/v1/dogs/?id=1 de http://api.animals.com/v1/dogs/?id=2. Différentes ressources en distingue que par la chaîne de requête. Donc l'action de votre demande, sauf si elle correspond directement à un sans corps existant type de méthode (TRACE, d'OPTIONS, de la TÊTE, GET, DELETE, etc) doit être définie dans le corps de la requête.

Ensuite, de décider si l'action est "idempotent", ce qui signifie qu'il peut être répété sans effet indésirable (voir le paragraphe suivant pour plus d'explanaton). Par exemple, la définition de la valeur de vérité peut être répétée si le client n'est pas certain que l'effet désiré est arrivé. Ils envoient à nouveau la demande et la valeur reste vrai. Ajouter 1 à un nombre n'est pas idempotent. Si le client envoie la Add1 de commande, n'est pas sûr, il a travaillé, et l'envoie de nouveau, ne le serveur ajouter un ou deux? Une fois que vous avez déterminé que vous êtes dans une meilleure position pour choisir entre PUT et POST de votre méthode.

Idempotent signifie une demande peut être répété sans changer le résultat. Ces effets ne comprennent pas forestières et autres admin serveur d'activité. À l'aide de votre première et deuxième exemples, l'envoi de deux e-mails à la même personne est dans un état autre que l'envoi d'un e-mail (le destinataire en a deux dans leur boîte de réception, ils peuvent considérer comme spam), donc je serais certainement utiliser POST pour que. Si le barkCount dans l'exemple 2 est destiné à être vu par un utilisateur de votre API ou affecte de quelque chose qui est client-visible, c'est aussi quelque chose qui en ferait la demande non-idempotent. Si c'est seulement pour être vu par vous, alors c'est comme un serveur d'enregistrement et doit être ignorée lors de la détermination de idempotentcy.

Enfin, de déterminer si l'action que vous souhaitez effectuer peut s'attendre à réussir immédiatement ou pas. BarkDog est rapidement à l'action. RunMarathon ne l'est pas. Si votre action est lente, envisager un retour à un 202 Accepted, avec une URL dans le corps de la réponse d'un utilisateur à un sondage pour voir si l'action est terminée. Sinon, demandez aux utilisateurs de publier une liste des URL de ce type /marathons-in-progress/ puis lorsque l'action est faite, les rediriger à partir de l'avancement de l'ID de l'URL de l' /marathons-complete/ d'URL.
Pour le cas #1 et #2, j'aurais l'hôte du serveur de file d'attente, et le poste client lots d'adresses. L'action ne serait pas SendEmails, mais quelque chose comme AddToDispatchQueue. Le serveur peut alors interroger la file d'attente pour voir si il y a des adresses e-mail d'attente, et d'envoyer des e-mails s'il en trouve. Il met ensuite à jour la file d'attente pour indiquer que l'attente de l'action a été effectuée. Vous auriez une autre URI indiquant le client de l'état actuel de la file d'attente. Pour éviter le double-envoi d'e-mails, le serveur peut également tenir un journal de qui il a envoyé cet e-mail, et vérifier chaque adresse par rapport à la que pour s'assurer qu'il n'envoie jamais les deux à la même adresse, même si vous affichez la même liste à deux reprises à la file d'attente.

Lors du choix d'un URI pour quoi que ce soit, essayez de penser comme un résultat, pas une action. Par exemple google.com/search?q=dogs montre les résultats d'une recherche pour le mot "chiens". Il n'a pas besoin d'effectuer la recherche.

Cas n ° 3 et n ° 4 à partir de votre liste sont également pas idempotent actions. Vous suggèrent que les différentes suggéré des effets pourraient influer sur la conception d'API. Dans les quatre cas, je voudrais utiliser la même API, comme tous les quatre de changer le "monde de l'état."

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X