web-dev-qa-db-fra.com

Pourquoi HTTP n'a-t-il pas de redirection POST?

Les redirections HTTP sont effectuées via les codes HTTP 301 et 302 (peut-être d'autres codes également) et un champ d'en-tête appelé "Emplacement" qui a l'adresse du nouvel endroit où aller. Cependant, les navigateurs envoient toujours une demande "GET" à cette URL.

Cependant, plusieurs fois, vous devez rediriger votre utilisateur vers un autre domaine via POST (paiements bancaires par exemple). Ceci est un scénario courant et vraiment une exigence. Quelqu'un sait-il pourquoi une telle exigence commune a été négligé dans la spécification HTTP? La solution consiste à envoyer un formulaire (avec des paramètres dans des champs masqués) avec une action définie à l'emplacement cible (la valeur du champ d'en-tête Location) et à utiliser setTimeout pour envoyer le formulaire à l'emplacement cible.

181
Saeed Neamati

Dans HTTP 1.1, il y a en fait un code d'état ( 7 ) qui indique que la demande doit être répétée en utilisant la même méthode et publier les données .

Comme d'autres l'ont dit, il existe un potentiel d'utilisation abusive ici, ce qui peut expliquer pourquoi de nombreux frameworks s'en tiennent aux 301 et 302 dans leurs abstractions. Cependant, avec une bonne compréhension et une utilisation responsable, vous devriez être en mesure d'accomplir ce que vous recherchez.

Notez que selon la spécification W3.org , lorsque METHOD n'est pas HEAD ou GET, les agents utilisateurs doivent demander à l'utilisateur avant de réexécuter la demande au nouvel emplacement. Vous devez également fournir une note et un mécanisme de secours à l'utilisateur au cas où les anciens agents utilisateurs ne seraient pas sûrs de ce qu'il faut faire avec un 307.

En utilisant ce formulaire:

<form action="Test307.aspx" method="post">
    <input type="hidden" name="test" value="the test" />
    <input type="submit" value="test" />    
</form>

Et ayant Test307.aspx renvoyer simplement 307 avec l'emplacement: http://google.com , Chrome 13 et Fiddler confirment que "test = le test" est en effet publié sur Google. Bien sûr, la réponse est un 405 puisque Google n'autorise pas le POST, mais il montre la mécanique.

Pour plus d'informations, voir Liste des codes d'état HTTP et spécification W3.org .

307 Redirection temporaire (depuis HTTP/1.1) Dans ce cas, la demande doit être répétée avec un autre URI, mais les demandes futures peuvent toujours utiliser l'URI d'origine . 2 Contrairement à 303, la méthode de demande ne doit pas être modifié lors de la réémission de la demande d'origine. Par exemple, une demande POST doit être répétée en utilisant une autre demande POST.

187
David Ruttka

J'ai trouvé une bonne explication à ce sujet page ici .

Les situations les plus simples sur le WWW sont des transactions "idempotentes", c'est-à-dire celles qui peuvent être répétées sans causer de dommages. Il s'agit généralement de transactions "GET", soit parce qu'elles sont la récupération de références URL simples (par exemple, href = ou src = attributs en HTML), soit parce qu'il s'agit de soumissions de formulaires utilisant la méthode GET. La redirection d'une transaction de ce type est simple et aucune question n'est posée: le client reçoit la réponse de redirection, y compris un en-tête Location: qui spécifie la nouvelle URL, et le client y réagit en réémettant la transaction vers la nouvelle URL. Il existe une différence entre les différents codes d'état 30x associés à ces redirections dans leur mise en cache implicite, mais sinon ils sont fondamentalement similaires (301 et 302) en réponse aux demandes GET.

Les transactions POST sont différentes, car elles sont définies comme étant, en principe, non idempotentes (comme commander une pizza, voter ou autre) et ne doivent pas être répétées arbitrairement.

Les spécifications du protocole HTTP sont conçues pour tenir compte de cette distinction: la méthode GET est définie comme étant intrinsèquement idempotente, tandis que la méthode POST est définie comme étant, au moins potentiellement, non idempotente; les spécifications appellent un certain nombre de précautions à prendre par les agents clients (tels que les navigateurs) pour protéger les utilisateurs contre (re) soumettre par inadvertance une transaction POST qu'ils n'avait pas voulu, ou soumettre un POST dans un contexte qu'ils n'auraient pas voulu.

Bien que je ne sois pas fan de restreindre techniquement les utilisateurs pour les empêcher de causer un chaos indésirable ou de nuire à leurs applications, je peux comprendre le point et cela a du sens.

49
Falcon

GET (et quelques autres méthodes) sont définis comme 'SAFE' dans la spécification http ( RFC 2616 ):

9.1.1 Méthodes sûres

Les implémenteurs doivent être conscients que le logiciel représente l'utilisateur dans leurs interactions sur Internet, et doivent veiller à permettre à l'utilisateur d'être au courant de toutes les actions qu'ils pourraient entreprendre et qui pourraient avoir une signification inattendue pour eux-mêmes ou pour les autres.

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

Naturellement, il n'est pas possible de garantir que le serveur ne génère pas d'effets secondaires suite à l'exécution d'une requête GET; en fait, certaines ressources dynamiques considèrent cette fonctionnalité. La distinction importante ici est que l'utilisateur n'a pas demandé les effets secondaires et ne peut donc pas en être tenu responsable.

Cela signifie qu'une demande GET ne devrait jamais avoir de conséquence sérieuse pour l'utilisateur, au-delà de voir quelque chose qu'il pourrait ne pas vouloir voir, mais une demande POST pourrait changer une ressource qui est importante pour lui ou pour les autres gens.

Bien que cela ait changé avec JavaScript, il y avait traditionnellement différentes interfaces utilisateur - les utilisateurs pouvaient déclencher des requêtes GET en cliquant sur des liens, mais devaient remplir un formulaire pour déclencher une requête POST. Je pense que les concepteurs de HTTP tenaient à maintenir la distinction entre les méthodes sûres et non sûres.

Je ne pense pas non plus qu'il soit nécessaire de rediriger vers un POST. Toute action qui doit être effectuée peut probablement être effectuée en appelant une fonction dans le code côté serveur, ou si elle doit se produire sur un autre serveur, au lieu d'envoyer une redirection contenant une URL pour le navigateur à POST to, le serveur pourrait faire une demande à ce serveur lui-même, agissant comme un proxy pour l'utilisateur.

2
bdsl