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

162

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 contient l’adresse du nouvel endroit où aller. Cependant, les navigateurs envoient toujours une requête "GET" à cette URL.

Cependant, il est souvent nécessaire de rediriger votre utilisateur vers un autre domaine via POST (paiements bancaires, par exemple). C’est un scénario courant et une nécessité. Est-ce que quelqu'un sait pourquoi une telle exigence commune a été négligée 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 sur l'emplacement cible (la valeur du champ d'en-tête Location ) et à utiliser setTimeoutpour soumettre le formulaire à l'emplacement cible.

Saeed Neamati
la source
1
Le code de statut 307 correspond-il à ce que vous recherchez? Voir ma réponse ci-dessous.
David Ruttka

Réponses:

180

Dans HTTP 1.1, il existe en réalité un code d'état ( 307 ) qui indique que la demande doit être répétée en utilisant la même méthode et les mêmes données de publication .

Comme d’autres l’ont dit, il existe un risque potentiel d’utilisation abusive, ce qui explique peut-être pourquoi de nombreux cadres restent fidèles aux normes 301 et 302. Cependant, avec une bonne compréhension et une utilisation responsable, vous devriez être capable de réaliser ce que vous cherchez.

Notez que, selon les spécifications de W3.org , lorsque ce METHODn'est pas le cas HEADou GET, les agents utilisateurs doivent informer 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 si les anciens agents utilisateurs ne savent pas quoi 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 après avoir Test307.aspx, il suffit de renvoyer 307 avec l'emplacement: http://google.com , Chrome 13 et Fiddler confirment que "test = le test" est effectivement posté sur Google. Bien sûr, la réponse suivante est un 405 puisque Google n'autorise pas le POST, mais cela montre les mécanismes.

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

307 Redirection temporaire (depuis HTTP / 1.1) À cette occasion, la requête doit être répétée avec un autre URI, mais les futures requêtes peuvent toujours utiliser l'URI d'origine. 2 Contrairement à 303, la méthode de requête ne doit pas être modifiée lors de la réémission de la requête d'origine. Par exemple, une demande POST doit être répétée à l'aide d'une autre demande POST.

David Ruttka
la source
2
@ David Ruttka, quel est le support du navigateur dans la nature ?
Pacerier
5
@ David Ruttka, vous voudrez peut-être mettre à jour votre réponse pour prendre en compte rfc7231 (obsolètes rfc2616). Inviter l'utilisateur est basé sur une exigence de rfc2616. Cette exigence est supprimée dans rfc7231 et rfc7231 introduit également l'exigence que les redirections 307 ne doivent pas changer de méthode de demande (que vous mentionnez dans votre devis à la fin de votre réponse).
Nibarius
Notez que, selon tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "les codes de redirection HTTP 301-306 NE DEVRAIENT PAS être utilisés sauf si le fournisseur de service est conscient que le client est en fait un utilisateur- agent "Il semble donc que les services ReSTful devraient utiliser 308 au lieu de 301. Cependant, ceci n’est qu’un brouillon.
Bruce Adams
49

J'ai trouvé une bonne explication sur cette page ici .

Les situations les plus simples sur le WWW sont les transactions "idempotentes", c'est-à-dire celles qui peuvent être répétées sans causer de préjudice. Il s’agit généralement de transactions "GET", soit parce qu’elles récupèrent des références d’URL simples (par exemple, href = ou src = en HTML), soit parce qu’elles sont des formulaires soumis à l’aide de 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: spécifiant la nouvelle URL, et le client réagit à cette transaction 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 capacité de mise en cache implicite, mais sinon, ils sont fondamentalement similaires (301 et 302) en réponse à des demandes GET.

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

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

Bien que je ne sois pas fan de la restriction technique des utilisateurs pour les empêcher de causer un chaos indésirable ou de causer des dommages non désirés à leurs applications, je peux comprendre le problème et cela a du sens.

Faucon
la source
une bonne partie du raisonnement s’applique aux jours où les intertubes étaient lents et peu fiables (ce qu’ils sont encore dans de nombreux endroits du monde). Je me souviens très bien du moment où je composais un numéro et je me déconnectais au hasard chaque fois que quelqu'un prenait le téléphone. Il était préférable de recharger la page et de voir l'état du serveur plutôt que de soumettre à nouveau des éléments et de risquer d'exécuter la même action deux fois.
zzzzBov
@ Falcon, augmenter le "compteur de visiteurs" serait-il considéré comme non idempotent? Si tel est le cas, presque aucun site Web ne fait actuellement des GETs idempotents ...
Pacerier
@Pacerier: Typiquement idempotent est interprété comme "idempotent de manière significative", par exemple, acheter le même objet deux fois, sans enregistrer deux visites. Sinon, vous auriez tout à fait raison. Mais, en réalité, la spécification aurait dû imposer aux serveurs d’être significativement idempotents si nécessaire, par exemple pour incorporer un ID dans la page afin d’empêcher les duplications - de ne pas demander au navigateur de poser à l’utilisateur une question à laquelle il n’a aucun moyen de répondre avec exactitude. Quoi qu'il en soit, empêcher une redirection d'un POST n'affecte pas idempotency; c'est simplement un message disant que la cible de la demande est en réalité là-bas.
Lawrence Dol
Je ne vois pas comment cela aurait du sens pour ce raisonnement. Supposons que je suis sur le site Web de la banque Chase et que je soumets un formulaire. J'ai déjà accepté / fait confiance à eux. Donc, s'ils doivent rediriger ces données vers une autre page, pourquoi devrais-je être d'accord à nouveau. Ou un autre exemple, Dites que je suis une personne qui désactive JavaScript par défaut. Un jour, je vais remplir une application hypothécaire en ligne et lorsque je soumets le formulaire, il contient des erreurs. Ce serait formidable si l'application peut rediriger (avec POST) vers la page que je viens de remplir pour pré-renseigner les données.
b01
@Flacon, il me faut la preuve que le fait de restreindre une redirection avec POST peut prévenir le chaos de quelque manière que ce soit. Puisque je dois d'abord faire confiance à l'application avec mes données, ils peuvent faire ce qu'ils veulent avec elle une fois qu'ils ont les données. Et je ne pense pas que les redirections soient plus vulnérables que les requêtes avec POST.
b01
3

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 développeurs doivent être conscients que le logiciel représente l'utilisateur dans leurs interactions sur Internet et veiller à permettre à l'utilisateur de prendre connaissance de toute action qu'il pourrait prendre et qui pourrait avoir une signification inattendue pour lui-même ou pour les autres.

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.

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

Cela signifie qu'une requête GET ne devrait jamais avoir de conséquence grave pour l'utilisateur, à part voir quelque chose qu'il ne voudrait peut-être pas voir, mais une requête POST pourrait modifier une ressource qui est importante pour lui ou pour d'autres personnes.

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

Je pense également qu'il ne devrait jamais être nécessaire de rediriger vers un poste. Toute action à effectuer peut vraisemblablement être effectuée en appelant une fonction dans le code côté serveur ou, si cela doit se produire sur un serveur différent, au lieu d’envoyer une redirection contenant une URL pour le navigateur vers POST, le serveur pourrait faire une demande à ce serveur lui-même, agissant comme un proxy pour l'utilisateur.

bdsl
la source