¿Cómo se envían los parámetros en una solicitud HTTP POST?

En una solicitud HTTP GET , los parámetros se envían como una cadena de consulta :

  http://example.com/page ? parameter = value & also = another 

En una solicitud HTTP POST , los parámetros no se envían junto con el URI.

¿Dónde están los valores? En el encabezado de solicitud? En el cuerpo de solicitud? Cómo se ve?

Los valores se envían en el cuerpo de la solicitud, en el formato especificado por el tipo de contenido.

Por lo general, el tipo de contenido es application/x-www-form-urlencoded , por lo que el cuerpo de la solicitud utiliza el mismo formato que la cadena de consulta:

 parameter=value&also=another 

Cuando utiliza una carga de archivo en el formulario, utiliza en su lugar la encoding multipart/form-data , que tiene un formato diferente. Es más complicado, pero por lo general no es necesario que le importe lo que parece, así que no mostraré un ejemplo, pero puede ser bueno saber que existe.

El contenido se coloca después de los encabezados HTTP. El formato de un HTTP POST es tener los encabezados HTTP, seguidos de una línea en blanco, seguidos por el cuerpo de la solicitud. Las variables POST se almacenan como pares clave-valor en el cuerpo.

Puede ver esto en el contenido sin formato de una Publicación HTTP, que se muestra a continuación:

 POST /path/script.cgi HTTP/1.0 From: frog@jmarshall.com User-Agent: HTTPTool/1.0 Content-Type: application/x-www-form-urlencoded Content-Length: 32 home=Cosby&favorite+flavor=flies 

Puede ver esto usando una herramienta como Fiddler , que puede usar para ver las cargas de solicitud y respuesta HTTP sin procesar enviadas a través del cable.

Respuesta corta: en solicitudes POST, los valores se envían en el “cuerpo” de la solicitud. Con los formularios web, lo más probable es que se envíen con un tipo de medio de application/x-www-form-urlencoded o multipart/form-data . Los lenguajes de progtwigción o marcos que se han diseñado para manejar solicitudes web generalmente hacen “The Right Thing ™” con tales solicitudes y le proporcionan un fácil acceso a los valores fácilmente decodificados (como $_REQUEST o $_POST en PHP, o cgi.FieldStorage() , flask.request.form en Python).


Ahora vamos a desviarnos un poco, lo que puede ayudar a entender la diferencia;)

La diferencia entre las solicitudes GET y POST es en gran medida semántica. También se “usan” de manera diferente, lo que explica la diferencia en cómo se pasan los valores.

GET ( sección pertinente de RFC )

Cuando ejecuta una solicitud GET , le pide al servidor una, o un conjunto de entidades. Para permitir que el cliente filtre el resultado, puede usar la llamada “cadena de consulta” de la URL. La cadena de consulta es la parte después de ? . Esto es parte de la syntax de URI .

Por lo tanto, desde el punto de vista de su código de aplicación (la parte que recibe la solicitud), deberá inspeccionar la parte de consulta de URI para obtener acceso a estos valores.

Tenga en cuenta que las claves y los valores son parte del URI. Los navegadores pueden imponer un límite en la longitud de URI. El estándar HTTP establece que no hay límite. Pero en el momento de escribir esto, la mayoría de los navegadores limitan los URI (no tengo valores específicos). GET solicitudes GET nunca se deben usar para enviar información nueva al servidor. Especialmente no documentos más grandes. Ahí es donde debes usar POST o PUT .

POST ( sección pertinente de RFC )

Al ejecutar una solicitud POST , el cliente está realmente enviando un nuevo documento al host remoto. Entonces, una cadena de consulta no tiene sentido (semánticamente). Por eso no tienes acceso a ellos en tu código de aplicación.

POST es un poco más complejo (y mucho más flexible):

Al recibir una solicitud POST, siempre debe esperar una “carga útil” o, en términos HTTP: un cuerpo del mensaje . El cuerpo del mensaje en sí mismo es bastante inútil, ya que no existe un formato estándar (por lo que puedo decir. ¿Quizá application / octet-stream?). El formato del cuerpo está definido por el encabezado Content-Type . Cuando se utiliza un elemento HTML FORM con method="POST" , generalmente se application/x-www-form-urlencoded . Otro tipo muy común es multipart / form-data si usa archivos cargados. Pero podría ser cualquier cosa , desde text/plain , sobre application/json o incluso una application/octet-stream .

En cualquier caso, si se realiza una solicitud POST con un tipo de Content-Type que no puede ser manejado por la aplicación, debe devolver un código de estado 415 .

La mayoría de los lenguajes de progtwigción (y / o web-frameworks) ofrecen una forma de de / codificar el cuerpo del mensaje desde / hasta los tipos más comunes (como application/x-www-form-urlencoded , multipart/form-data o application/json ) . Entonces eso es fácil. Los tipos personalizados requieren potencialmente un poco más de trabajo.

Usando un documento codificado con formato HTML estándar como ejemplo, la aplicación debe realizar los siguientes pasos:

  1. Lea el campo Content-Type
  2. Si el valor no es uno de los tipos de medios admitidos, devuelva una respuesta con un código de estado 415
  3. de lo contrario, decodifique los valores del cuerpo del mensaje.

Nuevamente, los lenguajes como PHP o los marcos web para otros lenguajes populares probablemente lo manejarán por usted. La excepción a esto es el error 415 . Ningún marco puede predecir qué tipos de contenido su aplicación elige para admitir y / o no admitir. Esto depende de ti.

PUT ( sección pertinente de RFC )

Una solicitud PUT se maneja prácticamente de la misma manera que una solicitud POST . La gran diferencia es que se supone que una solicitud POST permite al servidor decidir cómo (y si lo hace) crear un nuevo recurso. Históricamente (desde el ahora obsoleto RFC2616 fue crear un nuevo recurso como un “subordinado” (hijo) del URI al que se envió la solicitud).

Por el contrario, se supone que una solicitud PUT “deposita” un recurso exactamente en ese URI, y exactamente con ese contenido. Ni mas ni menos. La idea es que el cliente sea ​​responsable de elaborar el recurso completo antes de “PONERLO”. El servidor debe aceptarlo tal como está en la URL dada.

Como consecuencia, una solicitud POST generalmente no se usa para reemplazar un recurso existente. Una solicitud PUT puede hacer tanto crear como reemplazar.

Nota al margen

También hay ” parámetros de ruta ” que se pueden usar para enviar datos adicionales al control remoto, pero son tan poco comunes que no entraré en demasiados detalles aquí. Pero, como referencia, aquí hay un extracto de la RFC:

Aparte de los segmentos de punto en las rutas jerárquicas, un segmento de ruta se considera opaco por la syntax genérica. Las aplicaciones que producen URI a menudo usan los caracteres reservados permitidos en un segmento para delimitar los subcomponentes específicos del esquema o del manejador de desreferencia. Por ejemplo, los caracteres reservados de punto y coma (“;”) e iguales (“=”) a menudo se utilizan para delimitar parámetros y valores de parámetros aplicables a ese segmento. El carácter reservado de coma (“,”) a menudo se usa para fines similares. Por ejemplo, un productor de URI podría usar un segmento como “nombre; v = 1.1” para indicar una referencia a la versión 1.1 de “nombre”, mientras que otro podría usar un segmento como “nombre, 1.1” para indicar lo mismo. Los tipos de parámetros se pueden definir por semántica específica del esquema, pero en la mayoría de los casos la syntax de un parámetro es específica para la implementación del algoritmo de desreferenciación de URI.

No puede escribirlo directamente en la barra de URL del navegador.

Puede ver cómo se envían los datos POST en Internet con Live HTTP Headers, por ejemplo. El resultado será algo así

 http://127.0.0.1/pass.php POST /pass.php HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate DNT: 1 Referer: http://127.0.0.1/pass.php Cookie: passx=87e8af376bc9d9bfec2c7c0193e6af70; PHPSESSID=l9hk7mfh0ppqecg8gialak6gt5 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 30 username=zurfyx&pass=password 

En donde dice

 Content-Length: 30 username=zurfyx&pass=password 

serán los valores de publicación.

El tipo de medio predeterminado en una solicitud POST es application/x-www-form-urlencoded . Este es un formato para codificar pares clave-valor. Las llaves pueden ser duplicadas. Cada par clave-valor está separado por un carácter & , y cada clave está separada de su valor por un = carácter.

Por ejemplo:

 Name: John Smith Grade: 19 

Está codificado como:

 Name=John+Smith&Grade=19 

Esto se coloca en el cuerpo de la solicitud después de los encabezados HTTP.

Algunos de los servicios web requieren que coloque datos de solicitud y metadatos por separado. Por ejemplo, una función remota puede esperar que la cadena de metadatos firmados se incluya en un URI, mientras que los datos se publican en un cuerpo HTTP.

La solicitud POST puede verse semánticamente así:

 POST /?AuthId=YOURKEY&Action=WebServiceAction&Signature=rcLXfkPldrYm04 HTTP/1.1 Content-Type: text/tab-separated-values; charset=iso-8859-1 Content-Length: [] Host: webservices.domain.com Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: identity User-Agent: Mozilla/3.0 (compatible; Indy Library) name id John G12N Sarah J87M Bob N33Y 

Este enfoque combina lógicamente QueryString y Body-Post utilizando un único tipo de Content-Type que es una “instrucción de análisis” para un servidor web.

Tenga en cuenta: HTTP / 1.1 está envuelto con el #32 (espacio) a la izquierda y con el #10 (alimentación de línea) a la derecha.

Los valores de formulario en HTTP POST se envían en el cuerpo de la solicitud, en el mismo formato que la cadena de consulta.

Para obtener más información, consulte la especificación .

Antes que nada, diferenciemos entre GET y POST

Get: es la solicitud HTTP predeterminada que se realiza en el servidor y se utiliza para recuperar los datos del servidor y la cadena de consulta que viene después ? en un URI se usa para recuperar un recurso único.

este es el formato

 GET /someweb.asp?data=value HTTP/1.0 

aquí data=value es el valor de cadena de consulta pasado.

POST: se usa para enviar datos al servidor de forma segura, de modo que cualquier cosa que se necesite, este es el formato de una solicitud POST

 POST /somweb.aspHTTP/1.0 Host: localhost Content-Type: application/x-www-form-urlencoded //you can put any format here Content-Length: 11 //it depends Name= somename 

¿Por qué POST sobre GET?

En GET el valor que se envía a los servidores generalmente se agrega a la URL base en la cadena de consulta. Esto hace que sus datos puedan ser pirateados (esto fue un problema en días para Facebook donde se expusieron sus credenciales) por eso POST es utilizado para enviar datos al servidor que utilizó Request Body para enviar sus datos al servidor, que es más seguro porque oculta sus datos, además obtiene sus datos de los campos, calcula la longitud de los mismos y los agrega al header para content-length y no se añaden datos importantes directamente a la URL

ahora que su solicitud está segura, cualquier valor que se envíe al servidor se puede enviar en el Request Body la Request Body ya que el nombre implica que contendrá los datos que el usuario quería enviar (y se envía en formato URL Encoded ) y los Request Headers enviarán mantener segura la Solicitud al comparar los valores en el Request Body con los Request Headers

Puede usar la sección de red de Google Developer Tools para ver información básica sobre cómo se realizan las solicitudes a los servidores.

y siempre puede agregar más valores en sus Request Headers como Cache-Control , Origin , Accept .