Perché HTTP non ha il reindirizzamento POST?


162

I reindirizzamenti HTTP vengono effettuati tramite i codici HTTP 301 e 302 (forse anche altri codici) e un campo di intestazione noto come "Posizione" che ha l'indirizzo del nuovo posto dove andare. Tuttavia, i browser inviano sempre una richiesta "GET" a tale URL.

Tuttavia, molte volte è necessario reindirizzare l'utente a un altro dominio tramite POST (ad esempio pagamenti bancari). Questo è uno scenario comune e davvero un requisito. Qualcuno sa perché un requisito così comune è stato trascurato nelle specifiche HTTP? Per risolvere il problema, inviare un modulo (con parametri in campi nascosti) con azione impostata sulla posizione di destinazione (il valore del campo di intestazione Posizione ) e utilizzare setTimeoutper inviare il modulo alla posizione di destinazione.


1
Il codice di stato 307 è quello che stai cercando? Vedi la mia risposta qui sotto.
David Ruttka,

Risposte:


180

In HTTP 1.1, esiste effettivamente un codice di stato ( 307 ) che indica che la richiesta deve essere ripetuta utilizzando lo stesso metodo e post dati .

Come altri hanno già detto, esiste un potenziale uso improprio qui che può essere il motivo per cui molti framework si attengono a 301 e 302 nelle loro astrazioni. Tuttavia, con una comprensione adeguata e un uso responsabile, dovresti essere in grado di realizzare ciò che stai cercando.

Si noti che in base alle specifiche di W3.org , quando non lo METHODè HEADo GET, gli user agent dovrebbero richiedere all'utente prima di rieseguire la richiesta nella nuova posizione. Dovresti anche fornire una nota e un meccanismo di fallback per l'utente nel caso in cui i vecchi user agent non siano sicuri di cosa fare con un 307.

Utilizzando questo modulo:

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

E avere Test307.aspx restituisce semplicemente 307 con la posizione: http://google.com , Chrome 13 e Fiddler confermano che "test = il test" è effettivamente pubblicato su Google. Naturalmente l'ulteriore risposta è un 405 poiché Google non consente il POST, ma mostra la meccanica.

Per ulteriori informazioni, consultare Elenco dei codici di stato HTTP e le specifiche di W3.org .

307 Reindirizzamento temporaneo (da HTTP / 1.1) In questa occasione, la richiesta deve essere ripetuta con un altro URI, ma le richieste future possono comunque utilizzare l'URI originale. 2 Contrariamente a 303, il metodo di richiesta non deve essere modificato durante la riemissione della richiesta originale. Ad esempio, una richiesta POST deve essere ripetuta utilizzando un'altra richiesta POST.


2
@DavidRuttka, Qual è il supporto del browser in natura ?
Pacerier,

5
@DavidRuttka potresti voler aggiornare la tua risposta per tenere conto di rfc7231 (obsoletes rfc2616). La richiesta all'utente si basa su un requisito in rfc2616. Questo requisito viene eliminato in rfc7231 e rfc7231 introduce anche il requisito che 307 reindirizzamenti non devono modificare il metodo di richiesta (che citi nel tuo preventivo alla fine della tua risposta).
Nibario,

Si noti che secondo tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "I codici di reindirizzamento HTTP 301-306 NON DOVREBBERO essere utilizzati a meno che il fornitore del servizio non sia consapevole che il client è in realtà un utente- agente "Quindi sembra che i servizi ReSTful dovrebbero usare 308 invece di 301. Tuttavia questa è solo una bozza.
Bruce Adams,

49

Ho trovato una buona spiegazione in questa pagina qui .

Le situazioni più semplici sul WWW sono transazioni "idempotenti", cioè quelle che possono essere ripetute senza causare alcun danno. Si tratta in genere di transazioni "GET", sia perché vengono recuperati riferimenti URL semplici (ad esempio href = o src = attributi in HTML), sia perché sono invii di moduli mediante il metodo GET. Il reindirizzamento di una transazione di quel tipo è semplice e non vengono poste domande: il client riceve la risposta di reindirizzamento, inclusa un'intestazione Location: che specifica il nuovo URL, e il client reagisce ad esso emettendo nuovamente la transazione nel nuovo URL. C'è una differenza tra i diversi codici di stato 30x associati a questi reindirizzamenti nella loro cache implicita, ma per il resto sono sostanzialmente simili (301 e 302) in risposta alle richieste GET.

Le transazioni POST sono diverse, poiché sono definite, in linea di principio, non idempotenti (come ordinare una pizza, esprimere un voto o altro) e non devono essere ripetute arbitrariamente.

Le specifiche del protocollo HTTP sono progettate per tenere conto di questa distinzione: il metodo GET è definito intrinsecamente idempotente, mentre il metodo POST è definito, almeno potenzialmente, non idempotente; le specifiche richiedono una serie di precauzioni che gli agenti client (come i browser) devono adottare per proteggere gli utenti da (in) reindirizzamento involontario di una transazione POST che non avevano previsto o inoltrare un POST in un contesto che non avrebbero voluto .

Anche se non sono un fan di limitare tecnicamente gli utenti per impedire loro di causare caos indesiderati o di fare danni indesiderati alle loro applicazioni, posso capire il punto e ha senso.


gran parte del ragionamento va ai giorni in cui gli intertubes erano lenti e inaffidabili (che sono ancora in molte località del mondo). Ricordo distintamente quando usavo il dial-up e sarei stato disconnesso casualmente ogni volta che qualcun altro ha preso il telefono. Era meglio ricaricare la pagina e vedere in che stato si trovava il server piuttosto che inviare nuovamente le cose e correre il rischio di eseguire la stessa azione due volte.
zzzzBov,

@Falcon, Aumentare il "contatore visitatori" sarebbe considerato non idempotente? Se è così, quasi nessun sito web in questi giorni fa GET idempotenti ...
Pacerier,

@Pacerier: in genere idempotente viene interpretato come "idempotente in modo significativo", ad esempio acquistando lo stesso oggetto due volte, senza registrare due visite. Altrimenti, avresti ragione. Ma in realtà, le specifiche avrebbero dovuto richiedere che i server fossero significativamente idempotenti laddove necessario, come incorporare un ID nella pagina per evitare duplicazioni - non richiedendo al browser di porre all'utente una domanda a cui non hanno modo di rispondere con precisione. Indipendentemente da ciò, la prevenzione di un reindirizzamento di un POST non influisce sull'idempotenza; è semplicemente un messaggio che dice che l'obiettivo della richiesta è effettivamente lì.
Lawrence Dol,

Non vedo come questo abbia senso per questo ragionamento. Di 'che sono sul sito web della Chase Bank e che invio un modulo. Ho già accettato / fidato di loro. Quindi, se devono reindirizzare i dati su un'altra pagina, perché dovrei essere di nuovo d'accordo. O un altro esempio, dire che sono una persona che disattiva JavaScript per impostazione predefinita. Un giorno vado a compilare un'app di mutuo online e quando invio il modulo ha errori. Sarebbe bello se l'app potesse reindirizzare (con POST) alla pagina che ho appena compilato per precompilare i dati.
b01,

@Flacon, ho bisogno di prove del fatto che limitare un reindirizzamento con POST può prevenire il caos in ogni aspetto. Dal momento che devo prima fidarmi dell'app con i miei dati, possono fare tutto ciò che vogliono con esso una volta che hanno i dati. E non credo che i reindirizzamenti siano più vulnerabili della richiesta con POST.
b01,

3

GET (e alcuni altri metodi) sono definiti come "SICURI" nelle specifiche http ( RFC 2616 ):

9.1.1 Metodi sicuri

I responsabili dell'implementazione devono essere consapevoli del fatto che il software rappresenta l'utente nelle loro interazioni su Internet e dovrebbero fare attenzione a consentire all'utente di essere a conoscenza di eventuali azioni che potrebbero avere che potrebbero avere un significato inaspettato per se stessi o per gli altri.

In particolare, è stata stabilita la convenzione che i metodi GET e HEAD NON DOVREBBERO avere il significato di intraprendere un'azione diversa dal recupero. Questi metodi dovrebbero essere considerati "sicuri". Ciò consente agli interpreti utenti di rappresentare altri metodi, come POST, PUT e DELETE, in modo speciale, in modo che l'utente venga a conoscenza del fatto che viene richiesta un'azione potenzialmente non sicura.

Naturalmente, non è possibile garantire che il server non generi effetti collaterali a seguito dell'esecuzione di una richiesta GET; in effetti, alcune risorse dinamiche ritengono che una caratteristica. La distinzione importante qui è che l'utente non ha richiesto gli effetti collaterali, quindi non può essere ritenuto responsabile per loro.

Ciò significa che una richiesta GET non dovrebbe mai avere conseguenze gravi per l'utente, oltre a vedere qualcosa che potrebbe non voler vedere, ma una richiesta POST potrebbe cambiare una risorsa che è importante per loro o per altre persone.

Sebbene ciò sia cambiato con JavaScript, tradizionalmente c'erano diverse interfacce utente: gli utenti potevano attivare le richieste GET facendo clic sui collegamenti, ma avrebbero dovuto compilare un modulo per attivare una richiesta POST. Penso che i progettisti di HTTP abbiano voluto mantenere la distinzione tra metodi sicuri e metodi non sicuri.

Inoltre, non penso che dovrebbe mai essere necessario reindirizzare a un POST. Qualsiasi azione che deve essere eseguita può presumibilmente essere eseguita chiamando una funzione all'interno del codice lato server, oppure se deve avvenire su un server diverso, anziché inviare un reindirizzamento contenente un URL per il browser a POST al server potrebbe effettuare una richiesta al server stesso, fungendo da proxy per l'utente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.