web-dev-qa-db-fra.com

Comprendre REST: verbes, codes d'erreur et authentification

Je cherche un moyen de regrouper les API autour de fonctions par défaut dans mes applications Web, bases de données et CMS basés sur PHP.

J'ai regardé autour de moi et trouvé plusieurs cadres "squelettes". En plus des réponses à ma question, il existe Tonic , un cadre REST que j'aime bien car il est très léger.

J'aime bien REST le meilleur pour sa simplicité, et j'aimerais créer une architecture API basée sur celle-ci. J'essaie de comprendre les principes de base et je ne les ai pas encore bien compris. Par conséquent, un certain nombre de questions.

1. Est-ce que je comprends bien?

Disons que j'ai une ressource "utilisateurs". Je pourrais configurer un certain nombre d'URI comme ceci:

/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 architecture RESTful jusqu'à présent?

2. J'ai besoin de plus de verbes

Créer, mettre à jour et supprimer peut suffire en théorie, mais en pratique, j'aurai 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 ce sont des actions spécifiques qui peuvent avoir des codes de retour spécifiques et je ne voudrais pas les jeter toutes en une seule action .

Certains exemples qui viennent à l'esprit dans l'exemple d'utilisateur sont:

activate_login
deactivate_login
change_password
add_credit

comment pourrais-je exprimer des actions telles que celles d'une architecture d'URL RESTful?

Mon instinct serait de faire un appel GET à une URL comme

/api/users/1/activate_login 

et attendez un code d'état de retour.

Cela diffère de l'idée d'utiliser des verbes HTTP, cependant. Qu'est-ce que tu penses?

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

Une grande partie de la beauté de REST provient de son utilisation des méthodes HTTP standard. En cas d'erreur, j'émets un en-tête avec un code d'état d'erreur 3xx, 4xx ou 5xx. Pour une description détaillée de l'erreur, je peux utiliser le corps (non?). Jusqu'ici tout va bien. Mais quel serait le moyen de transmettre un code d'erreur propriétaire plus détaillé pour décrire ce qui n'allait pas (par exemple, "impossible de se connecter à la base de données", ou "erreur de connexion à la base de données")? Si je le mets dans le corps avec le message, je dois l'analyser par la suite. Existe-t-il un en-tête standard pour ce genre de chose?

4. Comment faire l'authentification

  • À quoi ressemblerait une authentification basée sur une clé API selon les principes REST?
  • Existe-t-il des points forts contre l'utilisation de sessions lors de l'authentification d'un client REST, outre le fait qu'il s'agit d'une violation flagrante du principe REST? :) (je ne plaisante pas à moitié ici, l'authentification basée sur la session fonctionnerait bien avec mon infrastructure existante.)
586
Pekka 웃

J'ai remarqué cette question avec quelques jours de retard, mais je sens que je peux ajouter un aperçu. J'espère que cela peut être utile pour votre projet RESTful.


Point 1: Est-ce que je comprends bien?

Tu as bien compris. C'est une représentation correcte d'une architecture RESTful. Vous pouvez trouver la matrice suivante de Wikipedia très utile pour définir vos noms et verbes:


Lorsqu'il s'agit d'un Collection URI du type: http://example.com/resources/

  • GET: Répertorie les membres de la collection, ainsi que leurs URI membres pour une navigation plus poussée. Par exemple, listez toutes les voitures à vendre.

  • PUT: Signification définie comme "remplacer la collection entière par une autre collection".

  • POST: Créez une nouvelle entrée dans la collection où l'ID est attribué automatiquement par la collection. L'ID créé est généralement inclus dans les données renvoyées par cette opération.

  • DELETE: Signification définie comme "supprimer toute la collection".


Lorsqu'il s'agit d'un Membre URI du type: http://example.com/resources/7HOU57Y

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

  • PUT: met à jour le membre adressé de la collection ou le crée avec l'ID spécifié.

  • POST: traite le membre adressé comme une collection à part entière et en crée un nouveau subordonné.

  • DELETE: Supprime le membre adressé de la collection.


Point 2: J'ai besoin de plus de verbes

En général, lorsque vous pensez avoir besoin de plus de verbes, cela peut signifier que vos ressources doivent être réidentifiées. Rappelez-vous que dans REST, vous agissez toujours sur une ressource ou sur une collection de ressources. Ce que vous choisissez comme ressource est très important pour la définition de votre API.

Activer/Désactiver la connexion: Si vous créez une nouvelle session, vous voudrez peut-être considérer "la session" comme ressource. Pour créer une nouvelle session, utilisez POST to _http://example.com/sessions/_ avec les informations d'identification contenues dans le corps. Pour l'expiration, utilisez PUT ou DELETE (selon que vous souhaitez ou non conserver un historique de session) à _http://example.com/sessions/SESSION_ID_.

Modifier le mot de passe: Cette fois, la ressource est "l'utilisateur". Vous auriez besoin d'un PUT pour _http://example.com/users/USER_ID_ avec l'ancien et le nouveau mots de passe dans le corps. Vous agissez sur la ressource "utilisateur" et un mot de passe de changement est simplement une demande de mise à jour. C'est assez similaire à l'instruction UPDATE dans une base de données relationnelle.

Mon instinct serait de faire un appel GET à une URL telle que _/api/users/1/activate_login_

Cela va à l'encontre d'un principe très fondamental REST: l'utilisation correcte des verbes HTTP. Toute demande GET ne doit jamais laisser d’effet secondaire.

Par exemple, une demande GET ne doit jamais créer une session sur la base de données, renvoyer un cookie avec un nouvel ID de session ou laisser des résidus sur le serveur. Le verbe GET ressemble à l'instruction SELECT dans un moteur de base de données. Rappelez-vous que la réponse à toute demande avec le verbe GET doit pouvoir être mise en cache si elle est demandée avec les mêmes paramètres, comme lorsque vous demandez une page Web statique.


Point 3: Comment renvoyer les messages d’erreur et les codes

Considérez les codes d’état HTTP 4xx ou 5xx comme des catégories d’erreur. Vous pouvez élaborer l'erreur dans le corps.

Échec de la connexion à la base de données:/Connexion incorrecte à la base de données: En général, vous devez utiliser une erreur 500 pour ces types d'erreur. Ceci est une erreur côté serveur. Le client n'a rien fait de mal. 500 erreurs sont normalement considérées comme "réutilisables". En d'autres termes, le client peut réessayer la même requête exacte et s'attendre à ce qu'il aboutisse une fois les problèmes du serveur résolus. Spécifiez les détails dans le corps, de sorte que le client puisse fournir un contexte à nous, humains.

L’autre catégorie d’erreurs serait la famille 4xx, ce qui indique en général que le client a fait quelque chose de mal. En particulier, cette catégorie d’erreurs indique normalement au client qu’il n’est pas nécessaire de réessayer la demande en l’état, car elle continuera d’échouer en permanence. c'est-à-dire que le client doit changer quelque chose avant de réessayer cette demande. Par exemple, les erreurs "Ressource non trouvée" (HTTP 404) ou "Requête malformée" (HTTP 400) tomberaient dans cette catégorie.


Point 4: Comment faire l'authentification

Comme indiqué au point 1, au lieu d'authentifier un utilisateur, vous pouvez envisager de créer une session. Un nouvel "ID de session" vous sera renvoyé, ainsi que le code d'état HTTP approprié (200: accès autorisé ou 403: accès refusé).

Vous demanderez alors à votre serveur RESTful: "Pouvez-vous m'obtenir la ressource pour cet ID de session?".

Il n'y a pas de mode authentifié - REST est sans état: vous créez une session, vous demandez au serveur de vous attribuer des ressources en utilisant cet ID de session en tant que paramètre et, lors de la déconnexion, vous supprimez ou expirez la session.

606
Daniel Vassallo

En termes simples, vous le faites complètement à l’arrière.

Vous ne devriez pas aborder ceci à partir des URL que vous devriez utiliser. Les URL viendront effectivement "gratuitement" une fois que vous aurez décidé quelles ressources sont nécessaires pour votre système ET comment vous allez les représenter, ainsi que les interactions entre les ressources et l'état de l'application.

Pour citer Roy Fielding

Une API REST devrait consacrer la quasi-totalité de ses efforts descriptifs à la définition du ou des types de support utilisés pour représenter les ressources et piloter l'état de l'application, ou à la définition de noms de relations étendues et/ou de balises hypertextes types de supports standard existants. Tous les efforts consacrés à la description des méthodes à utiliser pour les URI d’intérêt doivent être entièrement définis dans le cadre des règles de traitement pour un type de support (et, dans la plupart des cas, déjà définis par les types de support existants). [Un échec implique que les informations hors bande génèrent une interaction plutôt qu'un hypertexte.]

Les gens commencent toujours par les URI et pensent que c'est la solution, puis ils ont tendance à rater un concept clé de l'architecture [REST], notamment, comme indiqué plus haut: "Un échec implique ici que des informations hors bande sont: interaction de conduite au lieu de l'hypertexte ".

Pour être honnête, beaucoup voient beaucoup d'URI, des GET, des PUT et des POST et pensent que REST est facile. REST n'est pas facile. RPC sur HTTP est facile, il est facile de déplacer des blobs de données dans les deux sens via des charges HTTP. Reste, cependant, va au-delà de cela. REST est agnostique selon les protocoles. HTTP est juste très populaire et approprié pour les systèmes REST.

REST réside dans les types de média, leurs définitions et la façon dont l'application pilote les actions disponibles pour ces ressources via l'hypertexte (liens, de manière efficace).

Il existe différentes vues sur les types de média dans les systèmes REST. Certains privilégient les charges utiles spécifiques à l'application, tandis que d'autres, comme l'activation des types de média existants dans des rôles appropriés pour l'application. Par exemple, d'une part, vous avez des schémas XML spécifiques conçus pour votre application, par opposition à l'utilisation de quelque chose comme XHTML en tant que représentation, éventuellement par le biais de microformats et d'autres mécanismes.

Je pense que les deux approches ont leur place, le XHTML fonctionnant très bien dans des scénarios qui chevauchent à la fois le Web piloté par l’homme et celui piloté par la machine, alors que les types de données plus spécifiques, plus spécifiques, facilitent mieux les interactions entre machines. Je trouve que le développement des formats de produits peut rendre la négociation de contenu potentiellement difficile. "application/xml + yourresource" est beaucoup plus spécifique en tant que type de support que "application/xhtml + xml", car ce dernier peut s'appliquer à de nombreuses charges utiles qui peuvent ou non être quelque chose qui intéresse réellement un client d'ordinateur. déterminer sans introspection.

Cependant, XHTML fonctionne très bien (évidemment) dans le Web humain où les navigateurs Web et le rendu sont très importants.

Votre application vous guidera dans ce genre de décisions.

Une partie du processus de conception d'un système REST consiste à découvrir les ressources de première classe de votre système, ainsi que le dérivé, les ressources de support nécessaires pour prendre en charge les opérations sur les ressources principales. Une fois que les ressources sont découvertes, la représentation de ces ressources, ainsi que les diagrammes d'état indiquant le flux de ressources via l'hypertexte au sein des représentations, constituent le prochain défi.

Rappelez-vous que chaque représentation d'une ressource, dans un système hypertexte, combine à la fois la représentation réelle de la ressource et les transitions d'état disponibles pour la ressource. Considérez chaque ressource comme un nœud dans un graphique, les liens étant les lignes laissant ce nœud à d’autres états. Ces liens informent les clients non seulement de ce qui peut être fait, mais également de ce qui leur est demandé (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 parlera du champ rel nommé "utilisateurs" et du type de média "application/xml + youruser".

Ces liens peuvent sembler redondants, ils parlent tous à peu près au même URI. Mais ils ne sont pas.

En effet, pour la relation "utilisateurs", ce lien parle de la collection d'utilisateurs et vous pouvez utiliser l'interface uniforme pour travailler avec la collection (GET pour les récupérer tous, DELETE pour les supprimer tous, etc.).

Si vous POST à cette URL, vous devrez passer un document "application/xml + usercollection", qui ne contiendra probablement qu'une seule instance d'utilisateur dans le document afin que vous puissiez ajouter ou non l'utilisateur, peut-être, en ajouter plusieurs à la fois. Peut-être votre documentation suggérera-t-elle que vous pouvez simplement passer un type d'utilisateur unique, au lieu de la collection.

Vous pouvez voir ce que l’application requiert pour effectuer une recherche, comme défini par le lien "recherche" et son type de média. La documentation du type de média de recherche vous indiquera comment cela se comporte et ce à quoi vous attendre.

La conclusion à retenir est que les adresses URI elles-mêmes sont fondamentalement sans importance. L'application contrôle les URI et non les clients. Au-delà de quelques "points d’entrée", vos clients doivent s’appuyer sur les URI fournis par l’application pour son travail.

Le client doit savoir comment manipuler et interpréter les types de média, mais ne doit pas vraiment se soucier de l'endroit où il va.

Ces deux liens sont sémantiquement identiques chez un client:

<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"/>

Alors, concentrez-vous sur vos ressources. Concentrez-vous sur leurs transitions d'état dans l'application et sur la meilleure façon de les réaliser.

77
Will Hartung

re 1: Cela a l'air bien jusqu'à présent. N'oubliez pas de renvoyer l'URI de l'utilisateur nouvellement créé dans un en-tête "Location:" dans le cadre de la réponse à POST, avec un code d'état "201 Créé".

re 2: L'activation via GET est une mauvaise idée et inclure le verbe dans l'URI correspond à une odeur de design. Vous voudrez peut-être envisager de renvoyer un formulaire dans un environnement GET. Dans une application Web, il s'agirait d'un formulaire HTML avec un bouton d'envoi. Dans le cas d'utilisation de l'API, vous voudrez peut-être renvoyer une représentation contenant un URI vers PUT afin d'activer le compte. Bien entendu, vous pouvez également inclure cet URI dans la réponse du POST à/users. En utilisant PUT, votre demande sera idempotente, c’est-à-dire qu’elle pourra être renvoyée en toute sécurité si le client n’est pas sûr du succès. En général, réfléchissez aux ressources que vous pouvez utiliser pour transformer vos verbes (sorte de "nomenclature des verbes"). Demandez-vous quelle méthode votre action spécifique est le plus étroitement liée. Par exemple. change_password -> PUT; désactiver -> probablement DELETE; add_credit -> éventuellement POST ou PUT. Pointez le client sur les URI appropriés en les incluant dans vos représentations.

re 3. N'inventez pas de nouveaux codes de statut, à moins que vous ne pensiez qu'ils sont si génériques qu'ils méritent d'être normalisés à l'échelle mondiale. Essayez avec difficulté d’utiliser le code d’état le plus approprié (lisez la RFC 2616 pour en savoir plus sur chacun d’eux). Inclure des informations supplémentaires dans le corps de la réponse. Si vous êtes vraiment, vraiment sûr de vouloir inventer un nouveau code de statut, détrompez-vous; si vous le croyez toujours, assurez-vous de choisir au moins la bonne catégorie (1xx -> OK, 2xx -> informatif, 3xx -> redirection; 4xx-> erreur du client, 5xx -> erreur du serveur). Ai-je mentionné qu'inventer de nouveaux codes d'état est une mauvaise idée?

re 4. Si possible, utilisez le cadre d'authentification intégré à HTTP. Découvrez comment Google utilise l'authentification dans GData. En général, ne mettez pas de clés API dans vos URI. Essayez d'éviter les sessions pour améliorer l'évolutivité et prendre en charge la mise en cache. Si la réponse à une demande diffère en raison d'un événement antérieur, vous vous êtes généralement lié à une instance de processus serveur spécifique. Il est bien préférable de transformer l’état de la session en état du client (par exemple, l’inscrire dans les requêtes suivantes) ou de le rendre explicite en le transformant en état de ressource (serveur), c’est-à-dire en lui attribuant son propre URI.

30
Stefan Tilkov

1. Vous avez la bonne idée sur la façon de concevoir vos ressources, à mon humble avis. Je ne changerais rien.

2. Plutôt que d'essayer d'étendre HTTP avec plus de verbes, réfléchissez à ce que vos verbes proposés peuvent être réduits en termes de méthodes et de ressources HTTP de base. Par exemple, au lieu d'un verbe activate_login, vous pouvez configurer des ressources telles que: /api/users/1/login/active qui est un simple booléen. Pour activer un login, il suffit de PUT un document qui dit 'true' ou 1. Pour désactiver, PUT un document vide ou indiquant 0 ou faux.

De même, pour modifier ou définir des mots de passe, utilisez simplement PUTs sur /api/users/1/password.

Chaque fois que vous devez ajouter quelque chose (comme un crédit), pensez en termes de POSTs. Par exemple, vous pouvez créer un POST sur une ressource telle que /api/users/1/credits avec un corps contenant le nombre de crédits à ajouter. Une PUT sur la même ressource peut être utilisée pour écraser la valeur plutôt que pour ajouter. Un POST avec un nombre négatif dans le corps serait soustrait, et ainsi de suite.

. Je vous déconseille fortement d'étendre les codes d'état HTTP de base. Si vous ne trouvez pas celui qui correspond exactement à votre situation, choisissez le plus proche et mettez les détails de l'erreur dans le corps de la réponse. De plus, rappelez-vous que les en-têtes HTTP sont extensibles; votre application peut définir tous les en-têtes personnalisés que vous aimez. Une application sur laquelle j'ai travaillé, par exemple, pourrait renvoyer un 404 Not Found dans plusieurs circonstances. Plutôt que de faire analyser le corps de la réponse par le client pour la raison, nous avons simplement ajouté un nouvel en-tête, X-Status-Extended, qui contenait nos extensions de code d'état propriétaires. Donc, vous pourriez voir une réponse comme:

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

Ainsi, un client HTTP tel qu'un navigateur Web saura toujours quoi faire avec le code 404 standard, et un client HTTP plus sophistiqué pourra choisir de consulter l'en-tête X-Status-Extended pour obtenir des informations plus spécifiques.

4. Pour l'authentification, je vous recommande d'utiliser l'authentification HTTP si vous le pouvez. Mais à mon humble avis, il n’ya rien de mal à utiliser l’authentification basée sur les cookies si cela vous simplifie la tâche.

22
friedo

Bases de REST

REST a une contrainte d’interface uniforme, qui indique que le client REST doit s’appuyer sur des normes plutôt que sur les détails spécifiques à l’application du service REST actuel, de sorte que le client REST ne sera pas cassé par des changements mineurs, et il sera probablement réutilisable.

Il existe donc un contrat entre le client REST et le service REST. Si vous utilisez HTTP comme protocole sous-jacent, les normes suivantes font partie du contrat:

  • HTTP 1.1
    • définitions de méthodes
    • définitions de code d'état
    • en-têtes de contrôle de cache
    • accepte les en-têtes de type contenu
    • en-têtes d'authentification
  • IRI (utf8 URI )
  • body (en choisir un)
    • type MIME spécifique à une application enregistrée, par ex. labyrinthe + xml
    • type MIME spécifique au fournisseur, par exemple vnd.github + json
    • type MIME générique avec
      • RDF vocab spécifique à une application, par exemple. ld + json & hydra , schema.org
      • profil spécifique à l'application, par exemple hal + json & paramètre de lien de profil (je suppose)
  • hyperliens
    • ce qui devrait les contenir (choisissez-en un)
      • envoi en-têtes de liens
      • envoi d'une réponse hypermédia, par ex. html, atom + xml, hal + json, ld + json & hydra, etc ...
    • sémantique
      • utiliser les relations de lien IANA et probablement des relations de lien personnalisées
      • utiliser un RDF vocab spécifique à l'application

REST a une contrainte sans état, qui déclare que la communication entre le service REST et le client doit être sans état. Cela signifie que le service REST ne peut pas conserver les états du client, vous ne pouvez donc pas avoir de stockage de session côté serveur. Vous devez authentifier chaque demande. Ainsi, par exemple, l'authentification de base HTTP (partie de la norme HTTP) est acceptable car elle envoie le nom d'utilisateur et le mot de passe à chaque demande.

Pour répondre à vos questions

  1. Oui c'est possible.

    Il est à noter que les clients ne se soucient pas de la structure d'IRI, mais de la sémantique, car ils suivent des liens comportant des attributs de relations de lien ou de données liées (RDF).

    La seule chose importante à propos des IRI, c'est qu'un seul IRI ne doit identifier qu'une seule ressource. Une seule ressource, telle qu'un utilisateur, peut avoir plusieurs adresses IRI différentes.

    C’est assez simple de savoir pourquoi nous utilisons Nice IRI comme /users/123/password; Il est beaucoup plus facile d'écrire la logique de routage sur le serveur lorsque vous comprenez l'IRI simplement en le lisant.

  2. Vous avez plus de verbes, comme PUT, PATCH, OPTIONS, et bien plus encore, mais vous n'en avez pas besoin de plus… Au lieu d'ajouter de nouveaux verbes, vous devez apprendre à 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 la perspective REST en raison de la contrainte sans état.)

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

    Les en-têtes de statut HTTP sont vos en-têtes standard. Tout le reste devrait être dans le corps, je pense. Un seul en-tête ne suffit pas pour décrire, par exemple, des messages d'erreur multilingues détaillés.

  4. La contrainte sans état (avec les contraintes de cache et de système en couches) garantit la bonne évolutivité du service. Vous ne voudrez sûrement pas conserver des millions de sessions sur le serveur, alors que vous pouvez faire la même chose sur les clients ...

    Le client tiers reçoit un jeton d'accès si l'utilisateur y donne accès à l'aide du client principal. Après cela, le client tiers envoie le jeton d'accès à chaque demande. Il existe des solutions plus complexes, par exemple, vous pouvez signer chaque demande, etc. Pour plus de détails, consultez le manuel OAuth.

Littérature liée

12
inf3rno

Pour les exemples que vous avez mentionnés, j'utiliserais les éléments suivants:

activate_login

POST /users/1/activation

deactivate_login

DELETE /users/1/activation

changer le mot de passe

PUT /passwords (cela suppose que l'utilisateur est authentifié)

ajouter un crédit

POST /credits (cela suppose que l'utilisateur est authentifié)

Pour les erreurs, vous renverriez l'erreur dans le corps du format dans lequel vous avez reçu la demande, donc si vous recevez:

DELETE /users/1.xml

Vous renverriez la réponse en XML, il en irait de même pour JSON, etc.

Pour l'authentification, vous devez utiliser l'authentification http.

11
jonnii
  1. Utilisez post lorsque vous ne savez pas à quoi ressemblerait l'URI d'une nouvelle ressource (vous créez un nouvel utilisateur, l'application attribuerait au nouvel utilisateur son identifiant), PUT pour la mise à jour ou la création de ressources que vous savez comment elles vont être représentées (exemple : PUT /myfiles/thisismynewfile.txt)
  2. renvoyer la description de l'erreur dans le corps du message
  3. Vous pouvez utiliser l'authentification HTTP (si cela suffit), les services Web doivent être stateles
6
Arjan

Je suggérerais (dans un premier temps) que PUT ne devrait être utilisé que pour mettre à jour des entités existantes. POST devrait être utilisé pour en créer de nouveaux. c'est à dire.

/api/users     when called with PUT, creates user record

ne me sens pas bien. Le reste de votre première section (utilisation du verbe) semble toutefois logique.

5
Brian Agnew

Verbose, mais copié à partir de la spécification de la méthode HTTP 1.1 à l'adresse http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

9.3 GET

La méthode GET signifie extraire toutes les informations (sous la forme d'une entité) identifiées par l'URI de demande. Si l'URI de demande fait référence à un processus produisant des données, ce sont les données produites qui doivent être renvoyées en tant qu'entité dans la réponse et non le texte source du processus, à moins que ce texte ne se trouve être la sortie du processus.

La sémantique de la méthode GET devient "GET conditionnelle" si le message de demande comprend un champ d'en-tête If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match ou If-Range. Une méthode GET conditionnelle demande que l'entité ne soit transférée que dans les circonstances décrites par le ou les champs d'en-tête conditionnel. La méthode GET conditionnelle a pour but de réduire l'utilisation inutile du réseau en permettant aux entités mises en cache d'être actualisées sans nécessiter plusieurs requêtes ni transférer des données déjà détenues par le client.

La sémantique de la méthode GET devient "partielle GET" si le message de requête contient un champ d'en-tête Range. Une requête GET partielle demande que seule une partie de l'entité soit transférée, comme décrit à la section 14.35. La méthode GET partielle vise à réduire l'utilisation inutile du réseau en permettant aux entités partiellement récupérées d'être complétées sans transférer les données déjà détenues par le client.

La réponse à une demande GET peut être mise en cache si et seulement si elle répond aux exigences de la mise en cache HTTP décrite dans la section 13.

Voir la section 15.1.3 pour les considérations de sécurité lors de l'utilisation de formulaires.

9.5 POST

La méthode POST est utilisée pour demander au serveur d'origine d'accepter l'entité incluse dans la demande en tant que nouveau subordonné de la ressource identifiée par l'URI de demande dans la ligne de demande. POST est conçu pour permettre à une méthode uniforme de couvrir les fonctions suivantes:

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

La fonction réelle réalisée par la méthode POST est déterminée par le serveur et dépend généralement de l'URI de la demande. L'entité publiée est subordonnée à cet URI de la même manière qu'un fichier est subordonné à un répertoire qui le contient, qu'un article de presse est subordonné à un groupe de discussion auquel il est posté ou qu'un enregistrement est subordonné à une base de données.

L'action effectuée par la méthode POST peut ne pas aboutir à une ressource pouvant être identifiée par un URI. Dans ce cas, le statut de réponse approprié est soit 200 (OK), soit 204 (Sans contenu), selon que la réponse comprend ou non une entité qui décrit le résultat.

Si une ressource a été créée sur le serveur d'origine, la réponse DEVRAIT être 201 (Créé) et contenir une entité qui décrit l'état de la demande et fait référence à la nouvelle ressource, ainsi qu'un en-tête Location (voir la section 14.30).

Les réponses à cette méthode ne peuvent pas être mises en cache, sauf si la réponse inclut les champs d'en-tête Cache-Control ou Expires appropriés. Cependant, la réponse 303 (voir autre) peut être utilisée pour demander à l'agent d'utilisateur de récupérer une ressource pouvant être mise en cache.

Les demandes POST DOIVENT obéir aux exigences de transmission du message énoncées à la section 8.2.

Voir la section 15.1.3 pour les considérations de sécurité.

9.6 PUT

La méthode PUT demande à ce que l'entité incluse soit stockée sous l'URI de demande fourni. Si l'URI de demande fait référence à une ressource déjà existante, l'entité incluse DEVRAIT être considérée comme une version modifiée de celle résidant sur le serveur d'origine. Si Request-URI ne pointe pas vers une ressource existante et que cet URI peut être défini en tant que nouvelle ressource par l'agent utilisateur demandeur, le serveur d'origine peut créer la ressource avec cet URI. Si une nouvelle ressource est créée, le serveur d'origine DOIT informer l'agent d'utilisateur via la réponse 201 (Créé). Si une ressource existante est modifiée, les codes de réponse 200 (OK) ou 204 (pas de contenu) DEVRAIENT être envoyés pour indiquer que la demande a été complétée avec succès. Si la ressource ne peut pas être créée ou modifiée avec l'URI de demande, une réponse d'erreur appropriée DEVRAIT être donnée qui reflète la nature du problème. Le destinataire de l'entité NE DOIT PAS ignorer les en-têtes Content- * (par exemple, Content-Range) qu'il ne comprend pas ou ne met pas en œuvre et DOIT retourner une réponse 501 (non implémentée) dans de tels cas.

Si la demande passe par un cache et que l'URI de demande identifie une ou plusieurs entités actuellement mises en cache, ces entrées DEVRAIENT être traitées comme périmées. Les réponses à cette méthode ne peuvent pas être mises en cache.

La différence fondamentale entre les demandes POST et PUT est reflétée dans la signification différente de l'URI de demande. L'URI dans une demande POST identifie la ressource qui gérera l'entité incluse. Cette ressource peut être un processus acceptant les données, une passerelle vers un autre protocole ou une entité distincte acceptant les annotations. En revanche, l'URI dans une demande PUT identifie l'entité jointe à la demande - l'agent d'utilisateur sait ce que l'URI est destiné et le serveur NE DOIT PAS tenter d'appliquer la demande à une autre ressource. Si le serveur souhaite que la requête soit appliquée à un autre URI,

il DOIT envoyer une réponse 301 (déplacé de façon permanente); l'agent utilisateur PEUT alors prendre sa propre décision quant à l'opportunité de rediriger ou non la demande.

Une seule ressource PEUT être identifiée par de nombreux URI différents. Par exemple, un article peut avoir un URI identifiant "la version actuelle", qui est distinct de l'URI identifiant chaque version particulière. Dans ce cas, une demande PUT sur un URI général peut entraîner la définition de plusieurs autres URI par le serveur d'origine.

HTTP/1.1 ne définit pas comment une méthode PUT affecte l'état d'un serveur Origin.

Les demandes PUT DOIVENT obéir aux exigences de transmission des messages énoncées à la section 8.2.

Sauf indication contraire pour un en-tête d'entité particulier, les en-têtes d'entité de la demande PUT DEVRAIENT être appliqués à la ressource créée ou modifiée par le PUT.

9.7 SUPPRIMER

La méthode DELETE demande au serveur d'origine de supprimer la ressource identifiée par l'URI de demande. Cette méthode PEUT être remplacée par une intervention humaine (ou un autre moyen) sur le serveur Origin. Il n'est pas possible de garantir au client que l'opération a été effectuée, même si le code d'état renvoyé par le serveur Origin indique que l'action a été effectuée avec succès. Cependant, le serveur NE DEVRAIT PAS indiquer de succès sauf si, au moment où la réponse est donnée, il a l'intention de supprimer la ressource ou de la déplacer vers un emplacement inaccessible.

Une réponse réussie DEVRAIT être 200 (OK) si la réponse inclut une entité décrivant le statut, 202 (Acceptée) si l'action n'a pas encore été exécutée ou 204 (Aucun contenu) si l'action a été exécutée mais la réponse n'inclut pas. une entité.

Si la demande passe par un cache et que l'URI de demande identifie une ou plusieurs entités actuellement mises en cache, ces entrées DEVRAIENT être traitées comme périmées. Les réponses à cette méthode ne peuvent pas être mises en cache.

5
gahooa

À propos de REST codes de retour: il est incorrect de mélanger les codes de protocole HTTP et les résultats de REST.

Cependant, j'ai vu de nombreuses implémentations les mélanger et de nombreux développeurs pourraient ne pas être d'accord avec moi.

Les codes de retour HTTP sont liés au HTTP Request lui-même. Un appel REST est effectué à l'aide d'une demande Hypertext Transfer Protocol et fonctionne à un niveau inférieur à celui de la méthode invoquée REST. REST est un concept/une approche et son résultat est un résultat business/logical, alors que le code de résultat HTTP est un résultat transport.

Par exemple, renvoyer "404 non trouvé" lorsque vous appelez/utilisateurs/est confus, car cela peut vouloir dire:

  • L'URI est incorrect (HTTP)
  • Aucun utilisateur trouvé (REST)

"403 Interdit/Accès refusé" peut signifier:

  • Une autorisation spéciale est nécessaire. Les navigateurs peuvent le gérer en demandant à l'utilisateur/mot de passe. (HTTP)
  • Mauvaises autorisations d'accès configurées sur le serveur. (HTTP)
  • Vous devez être authentifié (REST)

Et la liste peut continuer avec une erreur "500 Server" (une erreur HTTP Apache/Nginx ou une erreur de contrainte commerciale dans REST) ​​ou d’autres erreurs HTTP, etc.

A partir du code, il est difficile de comprendre quelle était la raison de l'échec, une défaillance HTTP (transport) ou une défaillance REST (logique).

Si la requête HTTP a été correctement exécutée physiquement, elle doit toujours renvoyer le code 200, que les enregistrements soient ou non trouvés. Parce que la ressource URI est trouvée et a été gérée par le serveur http. Oui, cela peut retourner un jeu vide. Est-il possible de recevoir une page Web vide avec 200 comme résultat http, non?

Au lieu de cela, vous pouvez renvoyer 200 codes HTTP et simplement un JSON avec un tableau/objet vide, ou utiliser un indicateur bool result/success pour informer de l'état de l'opération effectuée.

De plus, certains fournisseurs d'accès à Internet peuvent intercepter vos demandes et vous renvoyer un code 404 http. Cela ne signifie pas que vos données ne sont pas trouvées, mais que quelque chose ne va pas au niveau du transport.

De Wiki :

En juillet 2004, le groupe de télécommunications britannique BT Group a déployé le système de blocage de contenu Cleanfeed, qui renvoie une erreur 404 à toute demande de contenu identifié comme potentiellement illégal par Internet Watch Foundation. D'autres fournisseurs de services Internet renvoient une erreur "interdite" HTTP 403 dans les mêmes circonstances. La pratique consistant à utiliser de fausses erreurs 404 comme moyen de dissimuler la censure a également été rapportée en Thaïlande et en Tunisie. En Tunisie, où la censure était sévère avant la révolution de 2011, les gens ont pris conscience de la nature des fausses erreurs 404 et ont créé un personnage imaginaire nommé "Ammar 404" qui représente "le censeur invisible".

2
Marcodor