Warum hat HTTP keine POST-Umleitung?

162

HTTP-Weiterleitungen erfolgen über die HTTP-Codes 301 und 302 (möglicherweise auch andere Codes) und ein als "Ort" bezeichnetes Header-Feld, das die Adresse des neuen Zielorts enthält. Browser senden jedoch immer eine "GET" -Anforderung an diese URL.

Häufig müssen Sie Ihren Benutzer jedoch per POST auf eine andere Domain umleiten (z. B. Bankzahlungen). Dies ist ein häufiges Szenario und eine echte Voraussetzung. Weiß jemand, warum eine solche gemeinsame Anforderung in der HTTP-Spezifikation vernachlässigt wurde? Die Abhilfe ist ein Formular zu senden (mit Parametern in versteckten Feldern) mit Wirkung auf die Zielposition (den Wert des Location - Header - Feldes) und verwenden Sie setTimeoutdas Formular an den Zielort zu senden.

Saeed Neamati
quelle
1
Ist der Statuscode 307 das, wonach Sie suchen? Siehe meine Antwort unten.
David Ruttka

Antworten:

180

In HTTP 1.1 gibt es tatsächlich einen Statuscode ( 307 ), der angibt, dass die Anforderung unter Verwendung derselben Methode und Post-Daten wiederholt werden sollte .

Wie andere bereits gesagt haben, besteht hier die Möglichkeit eines Missbrauchs , weshalb viele Frameworks in ihren Abstraktionen an 301 und 302 festhalten. Mit richtigem Verständnis und verantwortungsvollem Umgang sollten Sie jedoch in der Lage sein, das zu erreichen, wonach Sie suchen.

Beachten Sie, dass Benutzeragenten gemäß der W3.org-Spezifikation den Benutzer auffordern sollten, bevor sie die Anforderung am neuen Speicherort erneut ausführen , wenn dies METHODnicht der Fall ist HEADoder GETist . Sie sollten dem Benutzer auch einen Hinweis und einen Fallback-Mechanismus bereitstellen, falls alte Benutzerprogramme nicht sicher sind, was sie mit einem 307 tun sollen.

Mit diesem Formular:

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

Und wenn Sie Test307.aspx haben, geben Sie einfach 307 mit dem Standort zurück: http://google.com , Chrome 13 und Fiddler bestätigen, dass "test = the test" tatsächlich bei Google gepostet wird. Die weitere Antwort ist natürlich eine 405, da Google den POST nicht zulässt, aber die Mechanik zeigt.

Weitere Informationen finden Sie unter Liste der HTTP-Statuscodes und in der W3.org-Spezifikation .

307 Temporäre Umleitung (seit HTTP / 1.1) In diesem Fall sollte die Anforderung mit einer anderen URI wiederholt werden, zukünftige Anforderungen können jedoch weiterhin die ursprüngliche URI verwenden. 2 Im Gegensatz zu 303 sollte die Anforderungsmethode beim erneuten Ausgeben der ursprünglichen Anforderung nicht geändert werden. Beispielsweise muss eine POST-Anforderung mit einer anderen POST-Anforderung wiederholt werden.

David Ruttka
quelle
2
@DavidRuttka, Was ist die Browserunterstützung in freier Wildbahn ?
Pacerier
5
@ DavidRuttka Sie möchten möglicherweise Ihre Antwort aktualisieren, um rfc7231 zu berücksichtigen (obsoletes rfc2616). Das Auffordern des Benutzers basiert auf einer Anforderung in rfc2616. Diese Anforderung wird in rfc7231 gelöscht und rfc7231 führt auch die Anforderung ein, dass 307 Weiterleitungen die Anforderungsmethode nicht ändern dürfen (die Sie in Ihrem Angebot am Ende Ihrer Antwort erwähnen).
Nibarius
Beachten Sie, dass gemäß tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "die HTTP-Umleitungscodes 301-306 NICHT verwendet werden DÜRFEN , es sei denn, der Dienstanbieter weiß, dass der Client tatsächlich ein Benutzer ist. agent "Es scheint also, dass ReSTful - Dienste 308 anstelle von 301 verwenden sollten. Dies ist jedoch nur ein Entwurf.
Bruce Adams
49

Ich habe auf dieser Seite hier eine gute Erklärung gefunden .

Die einfachsten Situationen im WWW sind "idempotente" Transaktionen, dh solche, die wiederholt werden können, ohne Schaden zu verursachen. Dies sind in der Regel "GET" -Transaktionen, entweder weil sie einfache URL-Verweise abrufen (z. B. href = oder src = Attribute in HTML) oder weil sie Formularübermittlungen mit der GET-Methode sind. Das Umleiten einer Transaktion dieser Art ist unkompliziert und es werden keine Fragen gestellt: Der Client erhält die Umleitungsantwort, einschließlich eines Location: -Headers, der die neue URL angibt, und der Client reagiert darauf, indem er die Transaktion erneut an die neue URL ausgibt. Es gibt einen Unterschied zwischen den verschiedenen 30x-Statuscodes, die diesen Umleitungen zugeordnet sind, in ihrer impliziten Zwischenspeicherbarkeit, aber ansonsten sind sie als Reaktion auf GET-Anforderungen grundsätzlich ähnlich (301 und 302).

POST-Transaktionen sind unterschiedlich, da sie im Prinzip als nicht idempotent definiert sind (z. B. Pizza bestellen, abstimmen oder was auch immer) und nicht willkürlich wiederholt werden dürfen.

Die HTTP-Protokollspezifikationen berücksichtigen diese Unterscheidung: Die GET-Methode ist als inhärent idempotent definiert, während die POST-Methode als zumindest potenziell nicht idempotent definiert ist. Die Spezifikationen fordern eine Reihe von Vorsichtsmaßnahmen, die von Client-Agenten (wie z. B. Browsern) getroffen werden müssen, um Benutzer davor zu schützen, versehentlich eine POST-Transaktion (erneut) zu senden, die sie nicht beabsichtigt hatten, oder um einen POST in einem Kontext zu senden, den sie nicht gewollt hätten .

Ich mag es zwar nicht, Benutzer technisch einzuschränken, um zu verhindern, dass sie unerwünschtes Chaos anrichten oder ihren Anwendungen unerwünschten Schaden zufügen, aber ich kann den Punkt verstehen und es ist sinnvoll.

Falke
quelle
Ein Großteil der Überlegungen geht auf die Zeit zurück, als die Zwischenrohre langsam und unzuverlässig waren (was sie immer noch an vielen Orten der Welt sind). Ich erinnere mich genau, wann ich gewählt habe, und werde zufällig getrennt, wenn jemand anderes den Hörer abhebt. Es war besser, die Seite neu zu laden und festzustellen, in welchem ​​Status sich der Server befand, als Dinge erneut zu übermitteln und das Risiko einzugehen, dieselbe Aktion zweimal auszuführen.
zzzzBov
@ Falcon, Würde das Erhöhen des "Besucherzählers" als nicht idempotent angesehen werden? Wenn ja, tun fast keine Websites in diesen Tagen idempotente GETs ...
Pacerier
@ Pacerier: In der Regel wird idempotent als "idempotent auf sinnvolle Weise" interpretiert, z. B. indem ein Artikel zweimal gekauft wird und nicht zwei Besuche getaktet werden. Ansonsten hättest du recht. In der Tat sollte die Spezifikation vorausgesetzt haben, dass die Server bei Bedarf aussagekräftig und idempotent sind, z. B. durch Einbetten einer ID in die Seite, um Duplikate zu vermeiden. Der Browser muss dem Benutzer keine Frage stellen, die er nicht mit Genauigkeit beantworten kann. Unabhängig davon wirkt sich das Verhindern einer Umleitung eines POST nicht auf die Idempotenz aus. Es ist einfach eine Nachricht, die besagt, dass das Ziel der Anfrage tatsächlich dort drüben ist.
Lawrence Dol
Ich sehe keinen Sinn für diese Argumentation. Angenommen, ich bin auf der Chase-Bank-Website und sende ein Formular. Ich habe ihnen bereits zugestimmt / vertraut. Also, wenn sie diese Daten auf eine andere Seite umleiten müssen, warum sollte ich wieder zustimmen müssen. Oder ein anderes Beispiel: Angenommen, ich bin eine Person, die JavaScript standardmäßig deaktiviert. Eines Tages fülle ich eine Hypotheken-App online aus und wenn ich das Formular abschicke, sind Fehler aufgetreten. Es wäre großartig, wenn die App (mit POST) auf die Seite umleiten könnte, die ich gerade ausgefüllt habe, um die Daten vorab zu füllen.
b01
@Flacon, ich brauche den Beweis, dass das Einschränken einer Weiterleitung mit POST Chaos in jeder Hinsicht verhindern kann. Da ich der App zuerst meine Daten anvertrauen muss, können sie damit tun, was immer sie wollen, sobald sie die Daten haben. Und ich glaube nicht, dass Weiterleitungen anfälliger sind als Anfragen mit POST.
b01
3

GET (und einige andere Methoden) sind in der http-Spezifikation ( RFC 2616 ) als 'SAFE' definiert :

9.1.1 Sichere Methoden

Implementierer sollten sich darüber im Klaren sein, dass die Software den Benutzer bei seinen Interaktionen über das Internet repräsentiert, und sie sollten darauf achten, dass der Benutzer über mögliche Maßnahmen informiert wird, die für sich selbst oder andere eine unerwartete Bedeutung haben können.

Insbesondere wurde festgelegt, dass die Methoden GET und HEAD NICHT die Bedeutung haben DÜRFEN, eine andere Aktion als das Abrufen durchzuführen. Diese Methoden sollten als "sicher" angesehen werden. Auf diese Weise können Benutzerprogramme andere Methoden wie POST, PUT und DELETE auf besondere Weise darstellen, sodass der Benutzer auf die Tatsache aufmerksam gemacht wird, dass eine möglicherweise unsichere Aktion angefordert wird.

Natürlich kann nicht sichergestellt werden, dass der Server keine Nebenwirkungen infolge der Ausführung einer GET-Anforderung erzeugt. Einige dynamische Ressourcen betrachten dies sogar als eine Funktion. Der wichtige Unterschied hierbei ist, dass der Benutzer die Nebenwirkungen nicht angefordert hat und daher nicht für sie verantwortlich gemacht werden kann.

Dies bedeutet, dass eine GET-Anforderung keine schwerwiegenden Konsequenzen für den Benutzer haben sollte, abgesehen davon, dass sie etwas sieht, das er möglicherweise nicht sehen möchte. Eine POST-Anforderung kann jedoch eine Ressource ändern, die für ihn oder andere Personen wichtig ist.

Obwohl sich dies mit JavaScript geändert hat, gab es traditionell verschiedene Benutzeroberflächen - Benutzer konnten GET-Anforderungen durch Klicken auf Links auslösen, mussten jedoch ein Formular ausfüllen, um eine POST-Anforderung auszulösen. Ich denke, die Entwickler von HTTP waren daran interessiert, die Unterscheidung zwischen sicheren und nicht sicheren Methoden beizubehalten.

Ich denke auch nicht, dass es jemals notwendig sein sollte, zu einem POST umzuleiten. Jede Aktion, die ausgeführt werden muss, kann vermutlich durch Aufrufen einer Funktion innerhalb des serverseitigen Codes oder, wenn sie auf einem anderen Server ausgeführt werden muss, anstatt eine Umleitung mit einer URL für den Browser an den POST an den Server zu senden, ausgeführt werden könnte eine Anfrage an diesen Server selbst richten und sich wie ein Proxy für den Benutzer verhalten.

bdsl
quelle