Métodos GET vs POST del HTTP

Entendiendo el concepto de GET y POST

Muchas veces tenemos una idea equivocada sobre la utilización de GET y POST. Tendemos a entender que cuando doy click a un link eso es GET y cuando envío un formulario es POST. Mucho peor, solemos pensar que enviando peticiones POST los datos viajan seguros por no ir como parte de la URL como lo hace GET. Hay un error en este concepto que considero que cuando empezamos a aprender a usar tecnologías Web como por ejemplo PHP es entendible pero que a medida que vamos madurando debemos darnos cuenta que GET y POST no son la diferencia entre links y formularios.

Se suele prestar a confusión ya que tanto GET como POST son métodos del protocolo HTTP el cual esta compuesto por un envío al servidor conocido como petición (request) y una respuesta a dicha solicitud (response).

Protocolo HTTP

Tanto GET como POST, justamente por ser métodos ambos de HTTP, ejecutan un request y response, y a mi criterio esto suele ser parte de la confusión sobre los objetivos reales de ambos métodos.

Redefinamos los conceptos

El concepto GET es obtener información del servidor. Traer datos que están en el servidor, ya sea en un archivo o base de datos, al cliente. Independientemente de que para eso tengamos que enviar (request) algún dato que será procesado para luego devolver la respuesta (response) que esperamos, como por ejemplo un identificador para obtener una noticia de la base de datos.

POST sin embargo es enviar información desde el cliente para que sea procesada y actualice o agregue información en el servidor, como sería la carga o actualización en sí de una noticia. Cuando enviamos (request) datos a través de un formulario, estos son procesados y luego a través de una redirección por ejemplo devolvemos (response) alguna página con información.

Ambos métodos solicitan una respuesta del servidor y ahí es donde parecen que los conceptos son iguales ya que con ambos se podría lograr los mismos objetivos. Yo podría, aunque estaría mal, enviar por GET ciertos datos en la URL y “actualizar o insertar” información en mi base de datos, pero eso le correspondería al método POST. De la misma manera podría solicitar una página diferente por medio de POST y simplemente mostrarla como respuesta aunque eso debería ser a través de una llamada GET.

Las llamadas GET pueden ser cacheadas (historial del navegador), indexadas por buscadores, agregar los enlaces a nuestros favoritos o hasta pasar una url completa a otra persona para que directamente ingrese a esa página. Con el método POST sin embargo no se puede hacer esto.

Generalmente usamos links para ejecutar llamadas GET ya que la idea del link es simplemente “solicitar” una información (página) al servidor y que sea devuelta como una respuesta. Mientras usamos formularios para actualizar datos de productos, clientes, noticias, etc, también teniendo en cuenta que por el método POST también se puede enviar mucha más cantidad de datos que por GET.

Para entender finalmente la diferencia voy a darles un caso de análisis. Supongamos que tenemos en nuestro sitio ecommerce un listado de productos con un link que agregue ese producto al carrito de compras. Si hacemos que ese link ejecute el método GET, como generalmente lo usamos, usaríamos una URL parecida a esta: www.misitio.com/agregar_item_carrito.php?id=1. Al ser una llamada GET, Google podría indexar esa URL y podría aparecer en el buscador al buscar la palabra carrito. Cuando una persona le diera click automáticamente se ejecutaría esa página y agregaría el item con id 1 al carrito del sitio, lo cual les puedo asegurar que no es la idea ya que el visitante al buscar carrito debería querer simplemente entrar al sitio y no agregar un ítem que ni siquiera sabe cual es. Por lo tanto vemos que para este caso, por más que usemos un link, deberíamos de usar una llamada al método POST por ejemplo como lo usa el framework Symfony así:

<a onclick="f = document.createElement('form'); document.body.appendChild(f);
    f.method = 'POST'; f.action = this.href; f.submit();return false;"
    href="agregar_item_carrito.php?id=1">Agregar al carrito</a>

Lo que hace este link es muy sencillo, por medio del evento onclick de JavaScript, crea dinámicamente un formulario, le dice que será POST (ya que por defecto sería GET), le asigna la URL del enlace al action del form, envía el formulario y retorna false para no ejecutar el link en sí. Para hacer esto con Symfony simplemente usamos el helper link_to agregando la opción post=true:

<?php echo link_to('Agregar al carrito', 'agregar_item_carrito.php?id=1', 'post=true') ?>

Otro ejemplo sencillo sería cuando en un administrador de noticias tenemos un listado de las noticias con un link “eliminar” para borrarlas una por una (situación muy común en sistemas Web). Deberíamos de hacer esta petición usando POST para no permitir, por seguridad, que esa URL creada sea indexada, enviada a otra persona, guardada en favoritos, ni mucho menos ejecutada por culpa del botón atrás del navegador ya que quedaría cacheada en el historial.

Demos un ejemplo opuesto. Hay casos en los que los formularios de búsquedas al ser enviados por POST van a la página de resultados pero como estas llamadas no son cacheadas en el historial del navegador, no podemos volver usando la tecla atrás del navegador por lo que se suele dejar como llamadas GET a fin de ser cacheadas. Esto lo hacemos simplemente poniendo en el method del form la palabra get en lugar de post.

Espero que con esto se haya entendido la diferencia real entre los métodos GET y POST del protocolo HTTP y que cuando vayamos a utilizar un link o un formulario nos detengamos a pensar dos veces cual método es el más apropiado para no arriesgar la seguridad ni la consistencia del sitio.

Este es un artículo interesante para continuar con este tema.

En el siguiente artículo vamos a hablar sobre la forma de utilizar estos dos métodos con Ajax y jQuery.

Los comentarios son bienvenidos.

42 comentarios sobre “Métodos GET vs POST del HTTP”

  1. Genial artículo, tengo mucho de no programar para web y estoy retomándolo, así que lo primero que vino a mi mente fue esta cuestión; ya no recordaba la explicación que me dieron en la escuela.
    Me ayudó mucho, lo explicas de manera que no hay lugar a dudas.

    Bien.

  2. Muy buen artículo. Sobre todo muy didáctico y sencillo. No soy programador sino que hago gestión. Pero para entender lo que me estaban solicitando busqué, encontré tu artículo y ahora entiendo lo que me están pidiendo. Muchas gracias.

  3. Genial el artículo, me encuentro en la misma situación que Evelyn, desentumeciendo neuronas después de una buena temporada sin programar. Es curioso, lo importante que puede ser una cosa que a simple vista parece tan simple como el método del formulario.

    Muchas gracias por tu aporte a la comunidad 😉

    Seguiré de cerca tu blog.

    Un saludo!

  4. Gracias por el articulo, esta muy claro y con muy buenos ejemplos.

    Aun así tengo una duda al respecto. ¿Por que se usa un link para añadir un articulo y después se genera un formulario con javascript y no se hace con un formulario desde el principio?

    Gracias de nuevo.

    1. Dani. Este caso de suele utilizar cuando en lugar de poner como link el texto que ahora figura “Agregar al carrito”, quieres usar una imagen y lo puedes hacer rápidamente aprovechando una funcionalidad que existía en la versión.

      De todas formas la idea es ilustrar que generalmente cuando vemos un link, pensamos en GET, pero en realidad tiene ver con el objetivo, y en ese caso es POST ya que se quiere agregar un recurso.

  5. Gracias! La verdad es que cometía todos los fallos (confusiones) que mencionas.
    Ahora, al entender que GET puede ser cacheado o compartido como enlace se me aclara absolutamente todo.
    Oye… ¡que me has quitado una astilla que tenía clavada!
    Un saludo.

  6. Gracias por la información, es cierto y parte del problema es que muchos de los tutoriales de HTML, PHP y demás te dan a entender que entre POST y GET no hay diferencia salvo que la información está visible en la URL con GET siendo lo contrario con POST.

    Una duda que me quedaría es; En el ejemplo final que das de eliminar las noticias de un listado mencionas que se usaría POST para ello, y yo me pregunto ¿No se debería utilizar la petición DELETE de HTTP? Pregunto esto porque en dado caso pienso que sería el uso correcto del protocolo HTTP de otra manera quizá estaríamos cayendo en el mismo error de utilizar peticiones HTTP como nos funcione y no para lo que fueron creadas.

    ¿Estoy equivocado?

    Saludos.

    1. Estas completamente en lo cierto Roberto. Lo correcto es usar los verbos HTTPP para todas las acciones como lo puedes ver en los artículos que escribí sobre servicios REST. Para este artículo tomo en cuenta el POST para insert, update y delete porque es un siguiente paso tomando en cuenta que hay ocasiones en donde existen problemas con los navegadores a la hora de querer usar un verbo diferente a GET y POST por ejemplo en el action de un form y no te queda otra que usar un POST.

      Cuando trabajas con servicios REST ya es más fácil ya que por lo general no es el navegador el que invoca a los servicios, sino el action de tu front-end, y este es invocado desde un form por ejemplo.

  7. Muchas gracias, sos groso. Hace tres días empecé a aprender Java EE porque en todos los trabajos me los están requiriendo y nada mejor que comenzar a aprender una nueva tecnología usando buenos prácticas desde el comienzo.

    Saludos!

  8. Gracias por el articulo, lo encotre porque comenze a incursionar en el desarrollo WEB y estoy utilizando ASP.
    En los ejemplos usan if(IsPost) y por mas que busco en la documentación solo dice que IsPost = false cuando es la primera vez que se obtiene la pagina y true en ocaciones subcecuentes.
    Bueno, para no hacer el cuento largo la investigación me trajo a este articulo, y me surge una pregunta:
    Si actualizo la página que estoy viendo (presionando f5), ¿se hace un get o un post?
    De antemano gracias por la respuesta

    1. Si actualizas el navegador con el botón de actualizar o con el F5 es una llamada GET 🙂 a menos que haya venido de un POST por un formulario y ese caso los navegadores te muestran un mensaje diciéndote que se intentarán enviar nuevamente los datos.

  9. Pingback: Política de Privacidad de Mercado de Ideas - New Web Software
  10. Pingback: Política de Privacidad de Mercado de Ideas – New Web Software
  11. Problemas al Usar POST en HTML y el Método doPost en Servlets Java al Enviar Datos Confidenciales

    He diseñado una página web usando servlets con Java. Tengo los siguientes problemas:
    NOTA: No he usado FRAMEWORK alguno.

    PRIMER ERROR
    Cuando envío un formulario con POST los datos se registran correctamente, pero cuando actualizo con F5, ctrl + F5 ó hago click en la flechita circular que está junto a la barra de direcciones, aparece el mensaje:

    “Confirmar reenvío de formulario
    … Volver a la página podría provocar la repetición de alguna acción. ¿Quieres continuar?”

    Si acepto el mensaje, se repite la acción; y aparece dos registros iguales en mi base de datos.

    Qué hago para que una persona que quiera usar mi página web no reenvíe el formulario y solamente lo actualice cuando sea necesario.

    SEGUNDO ERROR
    Cuando hago enter dentro de la barra de direcciones, sale el siguiente mensaje:

    Error: HTTP method GET is not supported by this URL.

    En la universidad nos han dicho que cuando querramos enviar datos confidenciales usemos POST en HTML y doPost en los servlets.

    Si usara GET en HTML y doGet en los servlets, cómo protegería los datos confidenciales.

    NOTA: No he usado FRAMEWORK alguno.

    1. Luis

      La forma en la que se comporta el POST es así mismo como lo estás describiendo. Pero antes te aclaro que “los datos no irán seguros por usar POST”. Te explico:

      El método GET envía los datos por la URL, visibles directamente a todos, pero cuando envías datos por POST van en el cuerpo del Request y hay muchas formas de mirar ese contenido, es decir que podrías verlo exactamente igual aunque no estén visibles en la URL.

      Para hacer que tu sitio envíe datos seguros tienes que usar SSL, haciendo que tu sitio sea accedido por https y no por http. Así los datos que van por POST viajarán “encriptados” y los que vean el contenido no lo podrán interpretar.

      Con relación al mensaje que te aparece cuando el das F5, lo que ocurre es que los datos son enviados por debajo (POST), entonces si le das F5, para poder completarse la acción de envío, estos deben volver a enviarse. Esto también ocurre con GET solo que no te das cuenta porque cuando le das F5 se aceptan nuevamente los datos de la URL. Como el método GET debe ser usado para OBTENER datos entonces los navegadores no te lo advierten, pero como el POST es usado para procesar datos (inserts, updates, deletes, acciones específicas, etc), el navegador te advierte que serán nuevamente enviados.

      Una buena práctica es que después de cualquier envío POST, cómo última acción en el server, redirijas la página a una URL. Por ejemplo, suponte que tienes una página con un formulario, si entras por GET se muestra el formulario pero, si a la misma página entras por POST, se entiede que tienes que procesar el formulario que está llegando. Cuando envíes por POST, como última acción, redirige la página a la misma URL por GET, entonces cuando le den F5 al formulario ya se va a estar ejecutando el refresco de un nuevo formulario vacío. Esto lo puedes ver con un ejemplo con el framework Symfony aquí: https://symfony.com/doc/current/forms.html#handling-form-submissions. Presta atención a la línea 28.

      Ahora bien, si el procesamiento de tu form tarda y todavía no se redirige la página ahí no puedes hacer mucho. Si alguien la da F5 se podría duplicar la operación. El mayor problema con esto es cuando por ejemplo es un formulario de pago online para una tienda de e-commerce, ya que duplicar la opción sería comprar doble. Es por eso que Paypal advierte con un mensaje antes de accionar el submit diciendo que la operación puede durar un tiempo y que no refresque la página ya que la operación podría duplicarse, enviando siempre un mail al final para que el usuario sepa que la operación fue realizada.

      Espero que te haya servido la explicación.

    1. Cualquier método del HTTP (get, post, put, delete) va a devolverte los datos en plano y cualquiera que se ponga en el medio va a poder leer tus datos. Para agregar seguridad tenes que configurar SSL, así tu protocolo deja de ser http y se vuelve https y los datos van cifrados.

      Dependiendo de lo que quieras hacer podrías encriptar tus datos con algún algoritmo de encriptación también

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *