web-dev-qa-db-fra.com

HTTP POST avec les paramètres de requête d'URL - bonne idée ou pas?

Je conçois une API pour passer par HTTP et je me demande si l'utilisation de la commande HTTP POST, mais avec des paramètres de requête d'URL uniquement et sans corps de requête, est un bon choix.

Considérations:

  • "Bonne conception Web" nécessite l'envoi d'actions POST par des actions non idempotentes. C'est une action non-idempotente.
  • Il est plus facile de développer et de déboguer cette application lorsque les paramètres de la demande sont présents dans l'URL.
  • L'API n'est pas destiné à une utilisation généralisée.
  • Il semble que faire une demande POST sans corps demandera un peu plus de travail, par exemple. un en-tête Content-Length: 0 doit être explicitement ajouté.
  • Il me semble également qu'un POST sans corps est un peu contre les attentes de la plupart des développeurs et des frameworks HTTP.

L'envoi de paramètres sur une demande POST via la requête URL plutôt que sur le corps de la demande présente-t-il d'autres inconvénients ou avantages?

Edit: La raison en est que les opérations ne sont pas idempotentes et ont des effets secondaires autres que la récupération. Voir la spécification HTTP :

En particulier, la convention a été établie que les méthodes GET et HEAD NE DEVRAIENT PAS avoir l’importance de prendre une mesure autre que la récupération. Ces méthodes doivent être considérées comme "sûres". Cela permet aux agents d'utilisateur de représenter d'autres méthodes, telles que POST, PUT et DELETE, de manière spéciale, de sorte que l'utilisateur soit informé du fait qu'une action potentiellement dangereuse est demandée.

...

Les méthodes peuvent également avoir la propriété "idempotence" en ce sens que (mis à part les problèmes d'erreur ou d'expiration), les effets secondaires de N> 0 requêtes identiques sont les mêmes que pour une requête unique. Les méthodes GET, HEAD, PUT et DELETE partagent cette propriété. En outre, les méthodes OPTIONS et TRACE NE DEVRAIENT PAS avoir d’effets secondaires et sont donc intrinsèquement idempotentes.

424
Steven Huwig

Si votre action n'est pas idempotente, alors vous DEVEZ utilisez POST. Si vous ne le faites pas, vous ne faites que demander des ennuis en bout de ligne. GET, PUT et DELETE les méthodes sont obligatoire être idempotentes. Imaginez ce qui se produirait dans votre application si le client prélavait toutes les demandes GET possibles pour votre service - si cela pouvait entraîner des effets secondaires visibles pour le client, il y avait quelque chose qui n'allait pas.

Je conviens que l'envoi d'un POST avec une chaîne de requête, mais sans corps, semble étrange, mais je pense que cela peut être approprié dans certaines situations.

Pensez à la partie requête d'une URL en tant que commande de la ressource pour limiter la portée de la requête en cours. En règle générale, les chaînes de requête sont utilisées pour trier ou filtrer une requête GET (comme ?page=1&sort=title), mais je suppose que cela a du sens sur un POST de limiter également la portée (peut-être comme ?action=delete&id=5).

238
Don McCaughey

Tout le monde a raison: tenez-vous-en à POST pour les requêtes non idempotentes.

Qu'en est-il de l'utilisation d'une chaîne de requête URI et d'un contenu de requête? Eh bien, c’est HTTP valide (voir note 1), alors pourquoi pas!

C'est également parfaitement logique: les URL, y compris leur partie chaîne de requête, servent à localiser des ressources . Alors que les verbes de méthode HTTP (POST - et son contenu de requête facultatif) servent à spécifier des actions, ou que faire des ressources . Ce devrait être des préoccupations orthogonales. (Mais, ce ne sont pas des préoccupations parfaitement orthogonales pour le cas particulier ContentType = application/x-www-form-urlencoded, voir la note 2 ci-dessous.)

Remarque 1: La spécification HTTP (1.1) n'indique pas que les paramètres de requête et le contenu s'excluent mutuellement pour un serveur HTTP acceptant les demandes POST ou PUT. Ainsi, tout serveur est libre d'accepter les deux. C'est à dire. si vous écrivez le serveur, rien ne vous empêche de choisir d'accepter les deux (sauf peut-être un cadre inflexible). En règle générale, le serveur peut interpréter les chaînes de requête en fonction des règles souhaitées. Il peut même les interpréter avec une logique conditionnelle faisant référence à d'autres en-têtes tels que Content-Type également, ce qui conduit à la Note 2:

Remarque 2: si un navigateur Web est le moyen principal utilisé par les utilisateurs pour accéder à votre application Web, et application/x-www-form-urlencoded est le type de contenu qu'ils publient, alors vous devriez suivre les règles pour ce type de contenu. Et les règles pour application/x-www-form-urlencoded sont beaucoup plus spécifiques (et franchement, inhabituelles): dans ce cas, vous devez interpréter l'URI comme un ensemble de paramètres et non comme un emplacement de ressource. [C'est le même point d'utilité soulevé par Powerlord; qu’il peut être difficile d’utiliser des formulaires Web pour POST contenu sur votre serveur. Juste expliqué un peu différemment.]

Note 3: à quoi servent les chaînes de requête à l'origine? La RFC 3986 définit les chaînes de requête HTTP comme une partie d'URI fonctionnant comme un moyen non hiérarchique de localiser une ressource.

Au cas où les lecteurs qui poseraient cette question souhaiteraient demander quelle est la bonne architecture RESTful: le modèle d'architecture RESTful n'exige pas que les schémas d'URI fonctionnent de manière spécifique. L'architecture RESTful concerne d'autres propriétés du système, telles que la mise en cache des ressources, la conception des ressources elles-mêmes (leur comportement, leurs capacités et leurs représentations) et le fait de savoir si la capacité idempotence est satisfaite. Ou, en d’autres termes, obtenir une conception hautement compatible avec le protocole HTTP et son ensemble de verbes de méthode HTTP. :-) (En d’autres termes, l’architecture RESTful n’est pas très précise, car les ressources sont localisées .)

Remarque finale: parfois, les paramètres de requête sont utilisés pour d'autres éléments, qui ne sont ni la localisation de ressources, ni le contenu de codage. Avez-vous déjà vu un paramètre de requête tel que "PUT = true" ou "POST = true"? Ce sont des solutions de contournement pour les navigateurs qui ne vous autorisent pas à utiliser les méthodes PUT et POST. Bien que ces paramètres soient considérés comme faisant partie de la chaîne de requête d'URL (sur le réseau), je soutiens qu'ils ne font pas partie de la requête de l'URL en esprit .

123

Vous voulez des raisons? En voici un:

Un formulaire Web ne peut pas être utilisé pour envoyer une demande à une page qui combine GET et POST. Si vous définissez la méthode du formulaire sur GET, tous les paramètres sont dans la chaîne de requête. Si vous définissez la méthode du formulaire sur POST, tous les paramètres sont dans le corps de la demande.

Source: norme HTML 4.01, section Soumission de formulaire 17.1

62
Powerlord

Du point de vue de la programmation, pour le client, il regroupe les paramètres, les ajoute à l’URL et effectue un POST par rapport à un GET. Côté serveur, il évalue les paramètres entrants à partir de la chaîne de requête au lieu des octets publiés. Fondamentalement, c'est un lavage.

La manière dont des plates-formes clientes spécifiques fonctionnent avec les routines POSTet GET dans leur pile réseau, peut présenter des avantages/inconvénients, ainsi que la manière dont le serveur Web traite ces demandes. Selon votre implémentation, une approche peut être plus efficace que l'autre. Sachant que cela guiderait votre décision ici.

Néanmoins, du point de vue du programmeur, je préfère autoriser soit un POST avec tous les paramètres du corps, soit un GET avec tous les paramètres de l'URL, et ignorer explicitement les paramètres d'URL avec n'importe quel POST demande. Cela évite la confusion.

8
jro

Je pense qu'il serait toujours assez RESTful de disposer d'arguments d'interrogation identifiant la ressource sur l'URL tout en maintenant la charge de contenu limitée au corps POST. Cela semblerait séparer les considérations de "Qu'est-ce que j'envoie?" contre "à qui est-ce que je l'envoie?".

6
swizzcheez

Le camp RESTE a quelques principes directeurs que nous pouvons utiliser pour normaliser la façon dont nous utilisons les verbes HTTP. Ceci est utile lorsque vous construisez une API RESTful comme vous le faites.

En un mot: GET doit être en lecture seule, c’est-à-dire n’avoir aucun effet sur l’état du serveur. POST est utilisé pour créer une ressource sur le serveur. PUT est utilisé pour mettre à jour ou créer une ressource. DELETE est utilisé pour supprimer une ressource.

En d'autres termes, si votre action d'API modifie l'état du serveur, REST nous conseille d'utiliser POST/PUT/DELETE, mais pas GET.

Les agents utilisateurs comprennent généralement que faire plusieurs POST est mauvais et l’en avertissent, car l’intention de POST est de modifier l’état du serveur (par exemple, payer les marchandises à la caisse), et vous ne voudrez probablement pas fais ça deux fois!

Comparez à un GET que vous pouvez faire aussi souvent que vous le souhaitez (idempotent).

3
saille