Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 20 de marzo de 2018
HTTP Como sabemos, los conocidos códigos de estado HTTP 301 y 302 se usan para retornar al agente de usuario (normalmente, el navegador) una redirección, que viene a ser algo así como decirle “hey, el recurso que andas buscando ya no se encuentra aquí, sino en esta otra dirección”.

Presto y obediente, el browser interpretará esta orden navegando hacia la URL indicada en el encabezado location del resultado, es decir, generando una nueva petición de tipo GET y mostrando al usuario la página obtenida.

Un ejemplo del workflow de peticiones y respuestas de este tipo podría ser la siguiente:
// Petición:
GET /home/articles/welcome-to-my-blog.html HTTP/1.1
Host: www.myserver.com

// Respuesta:
HTTP/1.1 301 Moved Permanently
Location: http://www.myserver.com/blog/welcome-to-my-blog.html

// Nueva petición:
GET /blog/welcome-to-my-blog.html HTTP/1.1
Host: www.myserver.com
...
La diferencia entre el código 301 y 302 es que el primero de ellos indica al agente de usuario (sea un browser o aplicación cliente) que la redirección es permanente, esto es, que puede almacenar localmente la nueva ubicación y utilizarla en el futuro con seguridad en lugar de la que se usó originalmente. El código 302, en cambio, indica que la nueva ubicación es temporal y sólo debe ser utilizada en esta ocasión para dirigir la petición al lugar correcto.

Los códigos de estado HTTP 301 y 302 son válidos en la mayoría de escenarios, y permiten solucionar problemas como, entre otros, el cambio de ubicación nuestros recursos sin perder posicionamiento en buscadores, o implementar el patrón Post-Redirect-Get para mejorar un poco la experiencia de usuario y evitar dobles envíos de información en formularios.

Sin embargo, hay ocasiones en que la solución queda algo corta. Por ejemplo, si cambiamos de URL el endpoint de un servicio programado exclusivamente para ser invocado mediante peticiones de tipo POST o PUT, lo que nos interesaría sería que las peticiones a la dirección original retornaran una redirección indicando la nueva ubicación pero también informando al browser de que utilice sobre ella el mismo verbo de la petición original.

Por ello, y algunas otras razones que veremos después, el estándar HTTP amplió, hace ya bastante tiempo, el conjunto de códigos de redirección con tres nuevos miembros: HTTP 303, 307 y 308. Los dos primeros formaron parte de HTTP 1.1, mientras que el código 308 fue añadido en la RFC 7538 algo más adelante.

Veamos para qué sirve cada uno de ellos.

HTTP 303

El código de estado HTTP 303, “See other”, se creó básicamente porque el viejo estado HTTP 302 estaba siendo implementado de forma incorrecta por los navegadores y generaba demasiadas ambigüedades.

Un resultado HTTP 303 indica expresamente que el browser debe realizar una nueva petición, obligatoriamente de tipo GET, hacia la ubicación indicada en el encabezado location incluido en la respuesta.

Y seguro que os preguntaréis si esto no es así ya con los resultados HTTP 302. Pues… sí y no. El estándar original indicaba que al recibir un 302 los browsers debían ejecutar la nueva petición manteniendo el método HTTP original, pero muchas implementaciones ignoraron este aspecto y ejecutaban la redirección mediante una petición GET. Es decir, a día de hoy, no es posible prever cómo interpretará el cliente una respuesta HTTP 302 enviada desde el servidor.

Por tanto, el estado 303 es simplemente para hacer más previsible este comportamiento. El retorno HTTP 303 elimina ambigüedades porque indica expresamente que debe ser utilizada una petición GET a la hora de seguir la redirección.

HTTP 307

El resultado HTTP 307, “Temporary redirect” es básicamente igual que el 302, una redirección de carácter transitorio. La diferencia está en que HTTP 307 indica que el cliente no puede modificar el verbo utilizado en la petición original; es decir, si la petición al recurso original se efectuó con el método POST, la redirección utilizará también el método POST.

Gráficamente, la diferencia entre utilizar HTTP 302 y 307 como resultado de una petición POST sería la siguiente:

Petición POST con retorno HTTP 302 Petición POST con retorno HTTP 307
Petición POST con redirección HTTP 302    Petición POST con redirección HTTP 307

HTTP 308

Creo que la forma más rápida de definir esta redirección es que el código de estado HTTP 308 es al 301 lo que HTTP 307 al 302 :) Es decir, se trata de una redirección permanente que, al igual que HTTP 307, indica al browser que al seguir la redirección debe utilizar el método HTTP inicial en lugar de un simple GET que, por una interpretación errónea, es la implementación más frecuente.

De nuevo se trata de una medida para eliminar ambigüedades producidas por las implementaciones incorrectas del estándar HTTP de los navegadores, que, a pesar de lo que se indicaba para las redirecciones 301, se tomaban la libertad de cambiar al método GET a la ahora de seguirlas.

Así, un ejemplo de secuencia de llamadas y respuestas para una redirección de este tipo sería el siguiente:
// Petición original:
POST /something HTTP/1.1
Host: www.myserver.com

// Respuesta:
HTTP/1.1 308 Moved Permanently
Location: http://www.myserver.com/v2/something

// Siguiente petición:
POST /v2/something HTTP/1.1
Host: www.myserver.com

En resumen…

Creo que, en la práctica, el resumen de lo que hemos visto en este artículo podría ser el siguiente:
  • Debemos responder con redirecciones HTTP 303 cuando el destino de la misma deba ser accedido obligatoriamente mediante una petición de tipo GET.
  • Debemos utilizar retornos HTTP 307 cuando queremos que el cliente conserve el verbo HTTP original al seguir la redirección temporal.
  • Usaremos HTTP 308 para forzar la utilización del método de la petición original al seguir la redirección permanente.
Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!