Resumen

  • El RFC 1945 de mayo de 1996 llamaba al 302 «Moved Temporarily» y exigía confirmación antes de redirigir automáticamente un POST. El RFC 2068 de enero de 1997 conservó esa cautela, anotó que ciertos clientes convertían POST en GET y definió 303 «See Other» para recuperar una página mediante GET.
  • El RFC 2616 de junio de 1999 renombró el 302 como «Found» y afirmó que la mayoría de agentes existentes lo trataban como un 303: hacían GET a la dirección de Location sin importar el método inicial. Añadió 307 «Temporary Redirect» para expresar la conservación del método; 303 ya existía en 1997.
  • El RFC 9110 de junio de 2022 sigue permitiendo que un agente transforme POST en GET después de 302 por razones históricas. Bajo 307, el método no debe cambiar al seguir automáticamente la redirección. La elección decide si el cuerpo del formulario llega a la nueva dirección.

Mover la dirección no resuelve qué se envía

El RFC 1945, especificación HTTP/1.0 publicada en mayo de 1996, llamó al código 302 «Moved Temporarily». El recurso solicitado estaba por un momento en otra URL, indicada en la respuesta mediante Location. El cliente debía seguir usando la dirección original en el futuro porque el traslado podía cambiar. Para una petición GET parece una señal de tráfico sencilla: se pregunta aquí y se lee allá.

Un formulario enviado con POST altera el problema. El usuario puede haber escrito datos y solicitado una acción. ¿Se repite exactamente esa operación en la dirección nueva? El texto de 1996 prohibía que el navegador redirigiera automáticamente un POST sin confirmación del usuario. El cambio de destino podía modificar las condiciones en que había decidido remitir el formulario.

Una redirección contiene dos decisiones. Location indica dónde se dirige la petición siguiente. El método indica qué clase de petición sale hacia allí. Conservar POST puede trasladar el cuerpo del formulario a otro servidor. Cambiar a GET pide un recurso sin repetir el envío. Describir el 302 como un simple cambio de dirección oculta esa segunda mitad.

El primer estándar puso un freno al automatismo, aunque las páginas ya querían mostrar un resultado después de procesar formularios. El usuario había pulsado «Enviar» ante un servidor, no necesariamente autorizado a repetir los datos en una ubicación distinta. El navegador, sin embargo, debía decidir qué hacer cuando recibía la señal de traslado.

El 303 daba una orden clara; los clientes improvisaban con 302

El RFC 2068 de enero de 1997, primera especificación HTTP/1.1, mantuvo «Moved Temporarily» y la exigencia de confirmar la redirección automática de peticiones distintas de GET o HEAD. Una nota registró la discrepancia: algunos agentes HTTP/1.0 ya cambiaban POST a GET al seguir automáticamente un 302. Según la regla escrita, era un comportamiento erróneo.

El mismo documento creó el 303 «See Other». Permitía que un servidor respondiera al POST apuntando a otro recurso que el navegador debía recuperar mediante GET. Un script activado por POST podía completar su trabajo y mostrar después una página diferente. La nueva URI no era simplemente otro nombre para el recurso solicitado inicialmente. Era la respuesta visible a una acción ya ejecutada.

El cliente que convertía 302 en GET conseguía algo parecido sin que el servidor hubiese elegido el código explícito. Si la acción había terminado, el resultado podía verse sin reenvío del formulario. Si el servidor esperaba que el POST continuara en la ubicación temporal, recibía una petición de lectura en lugar de la operación. Un solo número transmitía dos instrucciones. El RFC de 1997 dejó constancia del desacuerdo cuando todavía estaba desarrollándose.

La mayoría de los navegadores obligó a abrir otra casilla

El RFC 2616 de junio de 1999 cambió el nombre del 302 a «Found». Su nota técnica fue más importante que el nuevo rótulo: los RFC de 1996 y 1997 no permitían cambiar el método en la redirección, pero la mayoría de los agentes existentes trataban 302 como 303 y hacían GET a la URI de Location sin importar el método original. «La mayoría» es la apreciación escrita por el estándar, no una tabla de versiones de navegador que inventemos hoy.

El documento ofreció alternativas. 303 seguía indicando que había otro recurso que recuperar mediante GET, a menudo la salida de un programa iniciado por POST. Existía desde 1997. El 307 «Temporary Redirect», incorporado al texto de 1999, hacía clara la opción contraria: el recurso estaba en otra URI de forma temporal, pero la petición debía conservar el método al seguirla automáticamente. Por fin un servidor podía separar el resultado que había que leer de la operación que había que continuar.

El 302 siguió vivo. El propio RFC 2616 señaló que muchos clientes antiguos no entendían 303 y que, por compatibilidad, podía usarse 302 porque la mayoría reaccionaba igual que ante 303. La recomendación dice mucho sobre cómo se fija una regla en Internet. La semántica limpia estaba escrita; el software instalado hacía que el viejo código ambiguo siguiera siendo útil.

En un formulario real, la diferencia pesa. Si el servidor ya guardó los datos, una página de confirmación leída por GET es un paso nuevo. Si quiere continuar el envío en una URI temporal, precisa conservar POST y el cuerpo. Usar 302 después de la divergencia dejaba a la costumbre del cliente una parte decisiva de la transacción.

La costumbre aparece en el estándar posterior

El RFC 9110, «HTTP Semantics», de junio de 2022 aún contiene la huella. Por razones históricas, un agente puede cambiar POST por GET tras un 302. «Puede» no ordena que todos lo hagan. Si el servidor quiere impedir esa transformación, el documento señala 307. Al seguir automáticamente un 307, el agente no debe cambiar el método.

El mismo RFC presenta 303 como una respuesta indirecta: se recupera otro recurso, normalmente mediante GET o HEAD, y se muestra como resultado de la petición original. Su explicación histórica describe la división de los primeros clientes entre mantener POST y usar GET, y la convergencia práctica hacia GET con 301 y 302. El texto normativo terminó por admitir el comportamiento extendido.

Conservar POST tampoco es una virtud automática. El método y el cuerpo pueden llegar a la nueva URI. Eso es exactamente lo que se necesita cuando una operación debe continuar allí, y exactamente por lo que importa conocer el destino. Cambiar a GET evita repetir ese cuerpo, pero no ejecuta una acción que de veras deba proseguir como POST. La respuesta correcta depende de la transacción, no de preferir el número nuevo.

Los documentos oficiales dejan una pieza concreta para otra investigación: no enumeran las versiones de cada navegador que empezaron a transformar el método. Harían falta registros fechados de implementación. La secuencia principal sí está escrita: regla restrictiva en 1996, discrepancia observada en 1997, práctica mayoritaria y 307 en 1999, permiso histórico en 2022.

El método también cruzaba la frontera

Un 3xx suele dibujarse como una flecha hacia una página desplazada. El caso 302 muestra que una petición lleva más que una dirección. POST puede contener datos y una decisión del usuario. Repetirlo en otra URI no equivale a pedir allí una página por GET. Location muestra el sitio; el código y el navegador determinan qué atraviesa la frontera.

Los clientes en funcionamiento hicieron habitual una respuesta. Los autores del protocolo no borraron esa realidad reafirmando el párrafo antiguo. Nombraron la discrepancia, añadieron un código para conservar el método y terminaron por permitir el cambio a GET bajo 302. Una norma gobierna programas que ya existen; puede ordenar las opciones futuras, pero no recuperar las peticiones enviadas ayer.

La lectura práctica quedó en tres números cercanos: 302 puede llevar un POST a GET; 303 manda recuperar otro recurso; 307 conserva el método en un traslado temporal automático. El formulario toma caminos distintos según el número elegido. La ambigüedad del primero nació cuando los navegadores resolvieron la pregunta antes de que el papel alcanzara su práctica.

Fuentes