593 votes

La compréhension reste : Verbes, codes d’erreur et l’authentification

Je suis (comme un suivi de cette question) vous cherchez un moyen pour envelopper Api autour de fonctions par défaut dans mon PHP, applications web, bases de données et de Cms.

J'ai regardé autour et a trouvé plusieurs "squelette" des cadres. En plus des réponses à ma question, il est Tonique, un REPOS cadre que j'aime bien car il est très léger.

J'aime RESTE le meilleur pour sa simplicité, et voudrais créer une architecture API basée sur elle. Je suis en train d'essayer d'obtenir ma tête autour des principes de base et n'ont pas pleinement compris. Par conséquent, un certain nombre de questions.

1. Suis-je le comprendre, à droite?

Dire que j'ai une ressource "utilisateurs". Je pourrais établir un certain nombre de Uri comme suit:

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

est-ce une représentation correcte d'une bonne architecture?

2. J'ai besoin de plus de verbes

Créer, mettre à Jour et Supprimer suffira peut-être en théorie, mais en pratique, je vais avoir besoin de beaucoup plus de verbes. Je réalise que ce sont des choses qui pourraient être incorporées dans une demande de mise à jour, mais ils sont les mesures spécifiques qui ont des codes de retour et je ne veux pas les jeter tous en une seule action.

Certains qui viennent à l'esprit de l'utilisateur exemple:

activate_login
deactivate_login
change_password
add_credit

comment pourrais-je exprimer des actions telles que celles dans un cadre Reposant URL architecture?

Mon instinct serait de faire un appel à une URL du type

/api/users/1/activate_login 

et s'attendre à un code d'état de retour.

Qui s'écarte de l'idée d'utiliser les verbes HTTP. Qu'en pensez-vous?

3. Comment retourner des messages d'erreur et les codes

Une grande partie du RESTE de la beauté provient de son utilisation de méthodes HTTP. Sur une erreur, j'émets un en-tête avec un 3xx,4xx ou 5xx code d'état d'erreur. Pour une description détaillée de l'erreur, je peux utiliser le corps (à droite?). So far So good. Mais quel serait le moyen de transmettre un propriétaire code d'erreur qui est plus détaillé dans la description de ce qui s'est passé (par exemple, "impossible de se connecter à la base de données", ou "connexion de base de données mal")? Si je l'ai mis dans le corps du message, je dois l'analyser par la suite. Est-il un en-tête standard pour ce genre de chose?

4. Comment faire de l'authentification

  • Ce serait une API basée sur une clé d'authentification de REPOS après les principes?
  • Sont là les points forts à l'encontre de l'utilisation de sessions lors de l'authentification d'un client REST, d'autres que c'est une violation flagrante du principe RESTE? :) (seulement la moitié de blague ici, une session d'authentification voudrais bien jouer avec mon infrastructure existante.)

EDIT: Merci à tous pour votre grande les réponses les gars. Je m'en vais à travers eux, demain ou le jour d'après.

614voto

Daniel Vassallo Points 142049

J'ai remarqué cette question d'un couple de jours de retard, mais je sens que je peux ajouter un peu de perspicacité. J'espère que cela peut être utile à l'égard de votre Réparateur entreprise.


Point 1: Suis-je comprendre?

Vous l'avez compris le droit. C'est une représentation correcte d'une bonne architecture. Vous pouvez trouver la matrice suivante à partir de Wikipedia très utile dans la définition de vos noms et les verbes:


Lorsque vous traitez avec une Collection de URI comme: http://example.com/resources/

  • OBTENIR: Liste des membres de la collection, avec leur membre de l'Uri pour la navigation. Par exemple, la liste de toutes les voitures à la vente.

  • METTRE: Signification définie comme "remplacer l'ensemble de la collection, avec une autre collection".

  • POST: Créer une nouvelle entrée dans la collection, où l'ID est attribué automatiquement par le système de collecte. L'ID créé est habituellement incluse dans les données renvoyées par cette opération.

  • SUPPRIMER: Signification définie comme "supprimer l'intégralité de la collection".


Lorsque vous traitez avec un Membre de URI comme: http://example.com/resources/7HOU57Y

  • GET: récupère une représentation de la membre de la collection exprimée dans un type MIME approprié.

  • METTRE: mise à Jour de la membre de la collection ou de la créer avec l'ID spécifié.

  • POST: Traite le membre comme une collection dans son propre droit et crée un nouveau subalternes.

  • SUPPRIMER: Supprimer le membre de la collection.


Point 2: j'ai besoin de plus de verbes

En général, lorsque vous pensez que vous avez besoin de plus de verbes, il peut signifier que vos ressources doivent être ré-identifiés. Rappelez-vous que dans le RESTE vous êtes toujours agissant d'une ressource, ou sur un ensemble de ressources. Ce que vous choisissez comme la ressource est très importante pour votre définition de l'API.

Activer/Désactiver la Connexion: Si vous créez une nouvelle session, alors vous pourriez envisager de "la session" comme la ressource. Pour créer une nouvelle session, utilisez la POSTE à l' http://example.com/sessions/ avec les informations d'identification dans le corps. Expirer il utilisez PUT ou DELETE (peut-être en fonction de si vous avez l'intention de garder un historique de session) http://example.com/sessions/SESSION_ID.

Changer le Mot de passe: Cette fois, la ressource est "l'utilisateur". Vous avez besoin d'une mise à http://example.com/users/USER_ID avec l'ancien et le nouveau mot de passe dans le corps. Vous agissez sur "l'utilisateur" de la ressource, et un changement de mot de passe est simplement une demande de mise à jour. C'est assez similaire à l'instruction de mise à JOUR dans une base de données relationnelle.

Mon instinct serait de faire un appel pour une URL du type /api/users/1/activate_login

Cela va à l'encontre d'un très de base RESTE le principe: L'utilisation correcte des verbes HTTP. Toute demande ne devrait jamais quitter n'importe quel effet secondaire.

Par exemple, une demande doit jamais créer une session sur la base de données, de retour d'un cookie avec un nouvel ID de Session, ou laisse aucun résidu sur le serveur. Le verbe GET est comme l'instruction SELECT dans un moteur de base de données. Rappelez-vous que la réponse à toute demande avec le verbe GET doit être cache-mesure lors de la demande avec les mêmes paramètres, tout comme lorsque vous demandez une page web statique.


Point 3: Comment retourner des messages d'erreur et les codes

Envisager la 4xx ou 5xx HTTP status codes d'erreur catégories. Vous pouvez élaborer l'erreur dans le corps.

Impossible de se Connecter à la Base de données: / Incorrect Connexion de Base de données: En général, vous devez utiliser une erreur 500 pour ces types d'erreurs. C'est un serveur-côté d'erreur. Le client n'a rien fait de mal. 500 les erreurs sont normalement considérés comme des "renouvelable". par exemple, le client peut tester à nouveau la même demande, et s'attendre à réussir une fois le serveur de problèmes sont résolus. Spécifiez les détails dans le corps, de sorte que le client sera en mesure de fournir un contexte à nous les humains.

L'autre catégorie d'erreurs serait le 4xx de la famille, qui, en général, d'indiquer que le client a fait quelque chose de mal. En particulier, cette catégorie d'erreurs normalement indiquer au client qu'il n'est pas nécessaire de recommencer la demande comme il est, car il continuera à ne pas en permanence. par exemple, le client a besoin de changer quelque chose avant de tenter à nouveau cette demande. Par exemple, la "Ressource non trouvée" (HTTP 404) ou "Demande incorrecte" (HTTP 400) des erreurs serait tomber dans cette catégorie.


Point 4: Comment faire de l'authentification

Comme indiqué au point 1, au lieu de l'authentification d'un utilisateur, vous pouvez réfléchir à la création d'une session. Vous serez renvoyé une nouvelle "Session ID", avec les codes d'état HTTP 200: Accès Accordé ou 403: Accès Refusé).

Il vous sera ensuite demander à votre serveur RESTful: "Pouvez-vous me fournir une ressource pour cet ID de Session?".

Il n'y a pas de mode authentifié - REPOS est apatride: Vous créez une session, vous demandez au serveur de vous donner des ressources à l'aide de cet ID de Session en tant que paramètre, et sur déconnexion, vous déposez ou d'expiration de la session.

77voto

Will Hartung Points 57465

Tout simplement, vous le faites entièrement vers l'arrière.

Vous ne devriez pas être en train d'approcher à partir de ce que les Url que vous devriez utiliser. L'Url sera effectivement venir "gratuitement" une fois que vous avez décidé quelles sont les ressources nécessaires pour votre système ET comment vous allez représenter ces ressources, et les interactions entre les ressources et l'état de l'application.

Pour citer Roy Fielding

Une API REST devrait passer presque tous son descriptif effort dans la définition de l' le type de média(s) utilisée pour représenter les les ressources et la conduite de l'application l'état, ou dans la définition élargie concernant les noms et/ou hypertexte permis à mark-up pour les standard de types de médias. Tout l'effort dépensé décrire les méthodes à utiliser sur ce Uri d'intérêt doivent être entièrement définis dans le cadre de la les règles de traitement pour un type de média (et, dans la plupart des cas, déjà définis par les types de médias). [Défaut ici implique que out-of-band l'information est le moteur de l'interaction au lieu de l'hypertexte.]

Les gens commencent toujours avec les URIs et pense que c'est la solution, et puis ils ont tendance à manquer un concept clé dans le RESTE de l'architecture, notamment, cité ci-dessus, "l'Échec implique que out-of-band information est le moteur de l'interaction au lieu de l'hypertexte."

Pour être honnête, beaucoup de voir un tas d'Uri et certains Reçoit et Met en et des Postes et de penser RESTE est facile. Le REPOS n'est pas facile. RPC sur HTTP est facile, le déplacement de gouttes de données proxy via HTTP charges est facile. RESTE, cependant, va au-delà. Le REPOS est un protocole agnostique. HTTP est juste très populaire et apt pour le REPOS des systèmes.

RESTE vivant dans les types de médias, leurs définitions, et de la façon dont l'application des lecteurs les actions disponibles à ces ressources via hypertexte (liens, effectivement).

Il y a des point de vue différent sur les types de médias dans les autres systèmes. Certains faveur de l'application spécifique des charges utiles, tandis que d'autres comme édifiante existant types de médias dans des rôles qui sont adaptés à l'application. Par exemple, sur un côté, vous avez des schémas XML conçu adaptés à votre application ou utiliser quelque chose comme XHTML est votre représentation, peut-être à travers les microformats et d'autres mécanismes.

Les deux approches ont leur place, je pense, le XHTML qui fonctionne très bien dans les scénarios qui se chevauchent à la fois l'homme et de la machine entraînée web orienté, tandis que l'ancien, plus des types de données spécifiques, je me sens mieux faciliter la machine à la machine interactions. Je trouve le soutien des produits de base formats peuvent faire de la négociation de contenu potentiellement difficile. "application/xml+yourresource" est beaucoup plus spécifique comme un média de type "application/xhtml+xml", celles-ci peuvent s'appliquer à de nombreuses charges qui peuvent ou peuvent ne pas être quelque chose d'un client de machine est réellement intéressé, ni de déterminer sans l'introspection.

Cependant, XHTML fonctionne très bien (évidemment) l'homme dans le web, où les navigateurs web et le rendu est très important.

L'application vous guide dans ces types de décisions.

Une partie du processus de conception d'un RESTE du système est la découverte de la première classe de ressources dans votre système, ainsi que les dérivés, le soutien des ressources nécessaires pour soutenir les opérations sur les ressources primaires. Une fois que les ressources sont découvertes, la représentation de ces ressources, ainsi que l'état des diagrammes montrant les flux de ressources par hypertexte à l'intérieur de la représentation, car le prochain défi.

Rappelons que chaque représentation d'une ressource, dans un système hypertexte, combine à la fois la ressource réelle représentation avec les transitions d'état à la disposition de la ressource. Considérer chaque ressource d'un nœud dans un graphe, avec les liens les lignes de quitter ce nœud à d'autres états. Ces liens informer les clients non seulement ce qui peut être fait, mais ce qui est nécessaire pour eux d'être fait (comme un bon lien combine l'URI et le type de support requis).

Par exemple, vous pouvez avoir:

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

Votre documentation allons parler de la rel champ nommé "utilisateurs", et les médias de type "application/xml+youruser".

Ces liens peuvent sembler redondants, ils sont tous parler de la même URI, assez bien. Mais ils ne sont pas.

C'est parce que pour les "usagers" de la relation, le lien est en train de parler au sujet de la collecte des utilisateurs, et vous pouvez utiliser l'interface unique de travailler avec la collection (GET pour récupérer tous les de la, de les SUPPRIMER pour supprimer tous les d'eux, etc.)

Si vous postez un message à cette adresse, vous aurez besoin de passer d'une "application/xml+usercollection" du document, qui sera probablement contenir une seule instance d'utilisateur dans le document de sorte que vous pouvez ajouter à l'utilisateur, ou pas, peut-être, pour ajouter plusieurs à la fois. Peut-être que votre documentation suggèrent que vous pouvez tout simplement passer à un seul type d'utilisateur, au lieu de la collecte.

Vous pouvez voir ce que l'application a besoin pour effectuer une recherche, tel que défini par le lien "recherche" et c'est mediatype. La documentation pour la recherche type de support va vous dire comment il se comporte, et à quoi s'attendre comme résultats.

La vente à emporter ici, cependant, est l'Uri eux-mêmes sont fondamentalement pas d'importance. L'application est en contrôle de l'Uri, pas les clients. Au-delà de quelques "points d'entrée", vos clients doivent s'appuyer sur les Uri fourni par l'application à son travail.

Le client a besoin de savoir comment manipuler et interpréter les types de médias, mais n'a pas besoin de beaucoup de soins où il va.

Ces deux liens sont sémantiquement identiques dans une les clients les yeux:

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

Donc, se concentrer sur vos ressources. De se concentrer sur leurs transitions de l'état dans l'application et la façon dont c'est le mieux réalisé.

30voto

Stefan Tilkov Points 1253

re 1: Cela ressemble bien de loin. N'oubliez pas de retourner l'URI de l'utilisateur nouvellement créé dans une "location:" dans le cadre de la réponse à la POSTE, avec un "201 Créé le" code d'état.

re 2: Activation par OBTENIR est une mauvaise idée, et dont le verbe à l'URI est une conception de l'odorat. Vous pourriez envisager de retourner un formulaire sur un GET. Dans une application Web, ce serait un formulaire HTML avec un bouton de soumission; dans le cas d'utilisation de l'API, vous pouvez retourner une représentation qui contient un URI pour METTRE à pour activer le compte. Bien sûr, vous pouvez inclure cette URI dans la réponse sur le POST /utilisateurs, trop. Utilisation de PUT vous assurer que votre demande est la quantité, c'est à dire il peut en toute sécurité être envoyé à nouveau si le client n'est pas sûr de la réussite. En général, pensez à ce que les ressources que vous pouvez transformer votre les verbes en (sorte de "nounification de verbes"). Demandez-vous ce méthode de votre action spécifique est plus étroitement aligné avec. E. g. change_password -> MIS; désactiver -> probablement SUPPRIMER; add_credit -> éventuellement POST ou PUT. Point le client approprié Uri en les incluant dans vos déclarations.

re 3. Ne pas inventer de nouveaux codes d'état, sauf si vous pensez qu'ils sont tellement génériques qu'ils méritent d'être normalisée à l'échelle mondiale. Essayez difficile à utiliser le plus approprié code d'état disponibles (lire à propos de tous dans la RFC 2616). Inclure des informations supplémentaires dans le corps de la réponse. Si vous avez vraiment, vraiment sûr que vous voulez inventer un nouveau code d'état, détrompez-vous; si vous croyez encore donc, assurez-vous au moins à choisir la bonne catégorie (1xx -> OK, 2xx -> information, 3xx -> redirection; 4xx-> erreur du client, 5xx -> erreur serveur). Ai-je mentionné que d'inventer de nouveaux codes d'état est une mauvaise idée?

re 4. Si de toute façon possible, utilisez le cadre d'authentification intégré dans HTTP. Découvrez la façon dont Google ne l'authentification dans GData. En général, ne pas mettre les clés API dans votre Uri. Essayez d'éviter les séances d'améliorer l'évolutivité et la charge la mise en cache - si la réponse à une demande diffère en raison de quelque chose qui s'est passé avant, vous avez généralement lié à un serveur spécifique instance de processus. C'est beaucoup mieux de tourner à l'état de session dans le client de l'état (par exemple, font partie des demandes ultérieures) ou de le rendre explicite en la transformant en (serveur) des ressources de l'état, c'est à dire lui donner sa propre URI.

22voto

friedo Points 36209

1. Vous avez eu la bonne idée sur la façon de concevoir vos ressources, à mon humble avis. Je ne voudrais pas changer une chose.

2. Plutôt que d'essayer de prolonger HTTP avec plus de verbes, pensez à ce que votre proposition de verbes peuvent être réduites dans les conditions de base HTTP méthodes et les ressources. Par exemple, au lieu d'un activate_login verbe, vous pourriez mettre en place des ressources comme: /api/users/1/login/active qui est un simple booléen. Pour activer une connexion, juste PUT un document qui dit que "vrai" ou 1 ou quoi que ce soit. Pour le désactiver, PUT un document vide ou dit est 0 ou false.

De même, pour modifier ou définir des mots de passe, il suffit de faire PUTs pour /api/users/1/password.

Chaque fois que vous avez besoin d'ajouter quelque chose (comme un crédit) penser en termes de POSTs. Par exemple, vous pourriez faire un POST à une ressource comme /api/users/1/credits avec un corps contenant le nombre de points à ajouter. Un PUT sur la même ressource peut être utilisée pour remplacer la valeur plutôt que d'en ajouter. Un POST avec un nombre négatif dans le corps de la soustraction, et ainsi de suite.

3. J'avais déconseillons fortement l'extension de la base des codes d'état HTTP. Si vous ne pouvez pas en trouver un qui correspond à votre situation exactement, choisissez la plus proche et de mettre les détails de l'erreur dans le corps de la réponse. Aussi, rappelez-vous que les en-têtes HTTP sont extensibles; votre demande, vous pouvez définir tous les en-têtes personnalisés que vous le souhaitez. Une application qui j'ai travaillé, par exemple, pourrait revenir un 404 Not Found dans de multiples circonstances. Plutôt que de prendre le client analyser le corps de la réponse pour la raison, que nous venons d'ajouter une nouvelle tête, X-Status-Extended, qui contenait notre propre code d'état extensions. Donc vous pouvez voir une réponse comme:

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

De cette façon, un client HTTP, comme un navigateur web sera toujours savoir quoi faire avec les 404 du code, et en plus sophistiqué HTTP client peut choisir de regarder le X-Status-Extended - tête pour des informations plus spécifiques.

4. Pour l'authentification, je recommande d'utiliser l'authentification HTTP, si vous le pouvez. Mais à mon humble avis il n'y a rien de mal à utiliser le cookie d'authentification si c'est plus facile pour vous.

14voto

inf3rno Points 2989

RESTE Bases

RESTE une interface uniforme de la contrainte, qui stipule que le RESTE client doit reposer sur des standards lieu de l'application de certains détails de la réelle RESTE d'un service, le client RESTE ne casse pas par des changements mineurs, et il va probablement être réutilisable.

Il y a donc un contrat entre le client REST et le RESTE du service. Si vous utilisez HTTP comme protocole sous-jacent, alors que les normes suivantes font partie intégrante du contrat:

  • HTTP 1.1
    • les définitions de méthode
    • code d'état définitions
    • cache-têtes de contrôle
    • accepter et en-têtes content-type
    • auth-têtes
  • IRI (utf8 URI)
  • corps (en choisir un)
    • application type MIME spécifique, par exemple labyrinthe+xml
    • fournisseur type MIME spécifique, par exemple vnd.github+json
    • type MIME générique avec
      • les applications spécifiques de vocabulaire RDF, par exemple ld+json & hydra, schema.org
      • demande de profil spécifique, par exemple hal+json & lien profil de param (je suppose)
  • les liens hypertexte
    • ce que doit contenir (en choisir un)
      • envoi en lien les en-têtes
      • envoi dans un hypermédia de réponse, par exemple, html, atom+xml, hal+json, ld+json&hydra, etc...
    • la sémantique
      • l'utilisation de l'IANA lien de relations et probablement en lien personnalisé relations
      • l'utilisation d'une application spécifique RDF vocab

RESTE a un apatride contrainte, qui déclare que la communication entre le RESTE du service et le client doivent être apatrides. Cela signifie que le RESTE de service ne peuvent pas maintenir les clients états, de sorte que vous ne pouvez pas avoir un côté serveur de stockage de session. Vous devez vous authentifier à chaque demande unique. Ainsi, par exemple, HTTP basic auth (partie de la HTTP standard) est très bien, car il envoie le nom d'utilisateur et le mot de passe à chaque requête.

Pour répondre à vous questions

  1. Oui, il peut être.

    Juste pour mentionner, les clients ne se soucient pas de l'IRI structure, ils s'inquiètent de la sémantique, parce qu'ils suivent les liens ayant un lien de relations ou de données liées (RDF) les attributs.

    La seule chose importante à propos de l'IRIs, qu'un seul IRI doit identifier qu'une seule ressource. Il est permis à une seule ressource, comme un utilisateur, d'avoir de nombreux différents de l'IRIs.

    Il est assez simple pourquoi nous utilisons belle IRIs, comme /users/123/password; il est beaucoup plus facile d'écrire la logique de routage sur le serveur quand vous comprenez l'IRI simplement en le lisant.

  2. Vous avez plus de verbes, comme MIS, PATCH, les OPTIONS, et même plus, mais vous n'avez pas besoin de plus de... au Lieu de l'ajout de nouveaux verbes que vous avez à apprendre comment ajouter de nouvelles ressources.

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (La connexion n'a pas de sens de REPOS point de vue, en raison de la apatrides contrainte.)

  3. Vos utilisateurs ne se soucient pas pourquoi le problème existe. Ils veulent savoir que si il y a erreur ou de réussite, et probablement un message d'erreur qu'ils peuvent comprendre, par exemple: "Désolé, mais nous n'avons pas pu enregistrer votre message.", etc...

    Le statut HTTP en-têtes sont vos des en-têtes standard. Tout le reste doit être dans le corps je pense. Un seul en-tête n'est pas assez pour décrire par exemple détaillée multilingue messages d'erreur.

  4. Les apatrides contrainte (avec le cache et le système de couches contraintes) s'assure que le service évolue bien. Vous avez sûrement ne pas wan pas de maintenir des millions de sessions sur le serveur, lorsque vous pouvez faire de même sur les clients...

    La 3ème partie, le client obtient un jeton d'accès si l'utilisateur accorde l'accès à l'aide de la client principal. Après que la 3ème partie client envoie le jeton d'accès avec chaque demande. Il y a de plus compliqué solutions, par exemple, vous pouvez vous inscrire à chaque demande unique, etc. Pour de plus amples informations, consultez le OAuth manuel.

De la documentation

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