HTTP POST con parámetros de consulta de URL: ¿buena idea o no?
Estoy diseñando una API para utilizar HTTP y me pregunto si usar el comando HTTP POST, pero solo con parámetros de consulta de URL y sin cuerpo de solicitud, es una buena manera de hacerlo.
Consideraciones:
- El "buen diseño web" requiere que las acciones no idempotentes se envíen mediante POST. Esta es una acción no idempotente.
- Es más fácil desarrollar y depurar esta aplicación cuando los parámetros de solicitud están presentes en la URL.
- La API no está destinada a un uso generalizado.
- Parece que realizar una solicitud POST sin cuerpo requerirá un poco más de trabajo; por ejemplo, se
Content-Length: 0
debe agregar explícitamente un encabezado. - También me parece que un POST sin cuerpo va un poco en contra de las expectativas de la mayoría de los desarrolladores y de los marcos HTTP.
¿Existen más inconvenientes o ventajas al enviar parámetros en una solicitud POST a través de la consulta URL en lugar del cuerpo de la solicitud?
Editar: La razón por la que esto se está considerando es que las operaciones no son idempotentes y tienen efectos secundarios además de la recuperación. Vea la especificación HTTP :
En particular, se ha establecido la convención de que los métodos GET y HEAD NO DEBEN tener la importancia de realizar una acción distinta a la recuperación. Estos métodos deberían considerarse "seguros". Esto permite a los agentes de usuario representar otros métodos, como POST, PUT y DELETE, de una manera especial, para que el usuario sea consciente del hecho de que se está solicitando una acción posiblemente insegura.
...
Los métodos también pueden tener la propiedad de "idempotencia" en el sentido de que (aparte de los problemas de error o caducidad) los efectos secundarios de N > 0 solicitudes idénticas son los mismos que para una sola solicitud. Los métodos GET, HEAD, PUT y DELETE comparten esta propiedad. Además, los métodos OPTIONS y TRACE NO DEBEN tener efectos secundarios y, por lo tanto, son inherentemente idempotentes.
Si tu acción no es idempotente, entonces DEBES usar POST
. Si no lo hace, sólo se estará metiendo en problemas en el futuro. GET
y se requierePUT
que los métodos sean idempotentes. Imagínese lo que sucedería en su aplicación si el cliente estuviera precargando cada solicitud posible para su servicio; si esto causara efectos secundarios visibles para el cliente, entonces algo anda mal.DELETE
GET
Estoy de acuerdo en que enviar un mensaje POST
con una cadena de consulta pero sin cuerpo parece extraño, pero creo que puede ser apropiado en algunas situaciones.
Piense en la parte de consulta de una URL como un comando dirigido al recurso para limitar el alcance de la solicitud actual. Normalmente, las cadenas de consulta se utilizan para ordenar o filtrar una GET
solicitud (como ?page=1&sort=title
), pero supongo que tiene sentido POST
limitar también el alcance (quizás como ?action=delete&id=5
).
Todo el mundo tiene razón: siga con POST para solicitudes no idempotentes.
¿Qué pasa con el uso de una cadena de consulta URI y de contenido de solicitud? Bueno, es HTTP válido (ver nota 1), así que ¿por qué no?
También es perfectamente lógico: las URL, incluida su parte de cadena de consulta, sirven para localizar recursos. Mientras que los verbos del método HTTP (POST y su contenido de solicitud opcional) sirven para especificar acciones o qué hacer con los recursos. Esas deberían ser preocupaciones ortogonales. (Pero no son preocupaciones bellamente ortogonales para el caso especial de ContentType=application/x-www-form-urlencoded, consulte la nota 2 a continuación).
Nota 1: La especificación HTTP (1.1) no establece que los parámetros de consulta y el contenido sean mutuamente excluyentes para un servidor HTTP que acepta solicitudes POST o PUT. Entonces cualquier servidor es libre de aceptar ambos. Es decir, si escribe el servidor, no hay nada que le impida aceptar ambos (excepto tal vez un marco inflexible). Generalmente, el servidor puede interpretar cadenas de consulta según las reglas que desee. Incluso puede interpretarlos con lógica condicional que también se refiere a otros encabezados como Content-Type, lo que lleva a la Nota 2:
Nota 2: si un navegador web es la forma principal en que las personas acceden a su aplicación web y application/x-www-form-urlencoded es el tipo de contenido que publican, entonces debe seguir las reglas para ese tipo de contenido. Y las reglas para application/x-www-form-urlencoded son mucho más específicas (y francamente, inusuales): en este caso debe interpretar el URI como un conjunto de parámetros y no como una ubicación de recurso. [Este es el mismo punto de utilidad que planteó Powerlord; que puede resultar difícil utilizar formularios web para PUBLICAR contenido en su servidor. Simplemente lo expliqué de manera un poco diferente.]
Nota 3: ¿para qué sirven originalmente las cadenas de consulta? RFC 3986 define las cadenas de consulta HTTP como una parte de URI que funciona como una forma no jerárquica de localizar un recurso.
En caso de que los lectores que hagan esta pregunta deseen preguntar qué es una buena arquitectura RESTful: el patrón de arquitectura RESTful no requiere esquemas URI para funcionar de una manera específica. La arquitectura RESTful se ocupa de otras propiedades del sistema, como la capacidad de almacenamiento en caché de los recursos, el diseño de los recursos mismos (su comportamiento, capacidades y representaciones) y si se satisface la idempotencia. O en otras palabras, lograr un diseño que sea altamente compatible con el protocolo HTTP y su conjunto de verbos del método HTTP. :-) (En otras palabras, la arquitectura RESTful no es muy previsora en cuanto a cómo se ubican los recursos ).
Nota final: a veces los parámetros de consulta se utilizan para otras cosas, que no son ni localizar recursos ni codificar contenido. ¿Alguna vez has visto un parámetro de consulta como 'PUT=true' o 'POST=true'? Estas son soluciones para navegadores que no le permiten utilizar métodos PUT y POST. Si bien dichos parámetros se consideran parte de la cadena de consulta de la URL (en el cable), sostengo que no son parte de la consulta de la URL en espíritu .
¿Quieres razones? Aquí hay uno:
No se puede utilizar un formulario web para enviar una solicitud a una página que utiliza una combinación de GET y POST. Si configura el método del formulario en GET, todos los parámetros están en la cadena de consulta. Si configura el método del formulario en POST, todos los parámetros están en el cuerpo de la solicitud.
Fuente: Estándar HTML 4.01, sección 17.13 Envío de formulario