¿Cómo puedo lidiar con las limitaciones de longitud de la cadena de consulta HTTP GET y aún quiero ser RESTful?

84

Como se indica en http://www.boutell.com/newfaq/misc/urllength.html , la cadena de consulta HTTP tiene una longitud limitada. Puede estar limitado por el cliente (Firefox, IE, ...), el servidor (Apache, IIS, ...) o el equipo de red (firewall aplicativo, ...).

Hoy me enfrento a este problema con un formulario de búsqueda. Desarrollamos un formulario de búsqueda con muchos campos, y este formulario se envía al servidor como una solicitud GET, por lo que puedo marcar la página resultante.

Tenemos tantos campos que nuestra cadena de consulta tiene una longitud de 1100 bytes y tenemos un firewall que elimina las solicitudes HTTP GET con más de 1024 bytes. Nuestro administrador de sistema nos recomienda utilizar POST en su lugar para que no haya limitaciones.

Claro, POST funcionará, pero realmente siento una búsqueda como GET y no como POST. Así que creo que revisaré nuestros nombres de campo para asegurarme de que la cadena de consulta no sea demasiado larga y, si no puedo, seré pragmático y usaré POST.

Pero, ¿hay alguna falla en el diseño de los servicios RESTful? Si tenemos una longitud limitada en la solicitud GET, ¿cómo puedo enviar objetos grandes a un servicio web RESTful? Por ejemplo, si tengo un programa que hace que los cálculos basados en un archivo, y quiero ofrecer un servicio web REST como esto: http://compute.com?content=<base64 file>. Esto no funcionará porque la cadena de consulta no tiene una longitud ilimitada.

Estoy un poco perplejo ...

cbliard
fuente
2
¿Qué significa tranquilo en términos de su contexto? O parafraseando: ¿por qué GET es relajante y POST no? ¿Porque GET se puede construir usando una simple concatenación de cadenas? La limitación de la longitud de la consulta es para evitar la asignación de memoria dinámica en aplicaciones que están diseñadas para funcionar rápidamente.
khachik
5
Cuando quiero hacer una búsqueda, no quiero crear, borrar o actualizar algo, solo quiero recuperar datos, entonces no debería usar POST, DELETE o PUT, y debería usar GET. Así es como entendí REST, pero puedo estar equivocado al respecto
cbliard
GET no es adecuado para realizar búsquedas, porque los resultados de una búsqueda pueden cambiar con el tiempo. La infraestructura web a menudo permite el almacenamiento en caché de solicitudes GET. Si usa GET, corre el riesgo de obtener resultados obsoletos para las búsquedas. POST es el camino, como se recomienda a continuación.
occulus
15
Todo cambia con el tiempo ( en.wikipedia.org/wiki/Impermanence ), tal es la naturaleza del universo ... Pero GET debe usarse para la búsqueda porque la "acción de búsqueda" no cambia los resultados
Luxspes

Respuestas:

51

Según su descripción, en mi humilde opinión, debería usar un POST. POST sirve para poner datos en el servidor y, en algunos casos, obtener una respuesta. En su caso, realiza una búsqueda (envía una consulta al servidor) y obtiene el resultado de esa búsqueda (recupera el resultado de la consulta).

La definición de GET dice que debe usarse para recuperar un recurso ya existente. Por definición, POST es crear un nuevo recurso. Esto es exactamente lo que está haciendo: ¡crear un recurso en el servidor y recuperarlo! Incluso si no almacena el resultado de la búsqueda, creó un objeto en el servidor y lo recuperó. Como PeterMmm dijo previamente, puede hacer esto con un POST (crear y almacenar el resultado de la consulta) y luego usar un GET para recuperar la consulta, pero es más práctico hacer solo un POST y recuperar el resultado.

¡Espero que esto ayude! :)

jmpcm
fuente
2
Tiene razón, puedo verlo como un POST porque la búsqueda es un recurso volátil recién calculado. Pero todavía tengo problemas para ver el límite entre POST y GET. Si quiero buscar todos los libros de ciencia ficción en una biblioteca, obtendré una colección de recursos existentes, así que estoy tentado de usar un GET, pero propones verlo como POST porque la búsqueda es un recurso nuevo en sí mismo. Por lo tanto, la cadena de consulta en GET debe usarse solo para cambiar la representación de datos, pero no para filtrar datos. Estoy en lo cierto?
cbliard
8
POST no debe usarse para búsquedas, GET es lo que debe usarse, de esta manera puede compartir y almacenar en caché la URL resultante y los resultados, y aprovecha mejor la arquitectura RESTful de Internet
Luxspes
37
Esta respuesta suena más a intentar jugar con palabras. Según esa lógica, podemos hacer todo como solicitudes POST y seguir siendo RESTful.
supertonsky
9
Esta respuesta parece que un abogado me ha hablado :-) La pregunta es realmente "Tengo un caso GET, está bien. Pero mi cadena de consulta excede la longitud permitida. ¿Cómo lo manejo". Votar en contra de esta respuesta.
G. Stoynev
2
Si se siguió esa lógica, entonces cada solicitud está creando un recurso y recuperándolo.
Alex
66

La especificación HTTP en realidad aconseja utilizar POST al enviar datos a un recurso para su cálculo.

Su búsqueda parece un cálculo, no un recurso en sí. Lo que podría hacer si aún desea que los resultados de su búsqueda sean un recurso es crear un token para identificar ese resultado de búsqueda específico y redirigir al agente de usuario a ese recurso.

Luego, puede eliminar los tokens de resultados de búsqueda después de un período de tiempo.

Ejemplo

POST /search
query=something&category=c1&category=c2&...

201 Created
Location: /search/01543164876

entonces

GET /search/01543164876

200 Ok
... your results here...

De esta manera, los navegadores y los proxies aún pueden almacenar en caché los resultados de la búsqueda, pero usted está enviando sus parámetros de consulta mediante POST.

EDITAR

Para aclarar, 01543164876aquí representa un ID único para el recurso que representa su búsqueda. Esas 2 solicitudes básicamente significan: crear un nuevo objeto de búsqueda con estos criterios, luego recuperar los resultados asociados con el objeto de búsqueda creado.

Este ID puede ser un ID único generado para cada nueva solicitud. Esto significaría que su servidor filtrará objetos de "búsqueda" y tendrá que limpiarlos regularmente con una estrategia de almacenamiento en caché.

O puede ser un hash de todos los criterios de búsqueda que realmente representan la búsqueda solicitada por el usuario. Esto le permite reutilizar los ID, ya que volver a crear una búsqueda devolverá un ID existente que puede (o no) estar ya almacenado en caché.

Vincent Robert
fuente
¿Cómo aborda esto el requisito de OP sobre marcar la consulta?
Ruibarbo
2
@Rhubarb lo aborda claramente al crear un recurso para una búsqueda determinada.
maulik13
3
Esto ralentizará los resultados. Realice una publicación y luego realice un GET. agregará al menos 300ms más para obtener la búsqueda.
jaxxbo
El enlace a la fuente está muerto
Emobe
Estoy confundido, ¿qué hace el servidor entre el POST y el GET? ¿Almacena en caché los datos de búsqueda en el servidor y simplemente espera a que llegue la solicitud GET? Tendría que usar una identificación única para hacer eso, por lo que podría recuperar el caché. Tu respuesta es buena, pero seguramente no completa. Y el uso de caché haría que las cosas fueran menos apátridas.
Alexander Mills
5

REST es una forma de hacer las cosas, no un protocolo. Incluso si no le gusta POST cuando en realidad es un GET, funcionará.

Si debe / debe permanecer con la definición "estándar" de GET, POST, etc. que quizás considere POST una consulta, esa consulta se almacenará en el servidor con un ID de consulta y solicitará la consulta más tarde con GET by id.

PeterMmm
fuente
4

Con respecto a su ejemplo:, http://compute.com?content={base64file}usaría POST porque está cargando "algo" para ser calculado. Para mí, este "algo" se siente más como un recurso que como un parámetro simple.

En contraste con esto en la búsqueda habitual, comenzaría a seguir con GET y los parámetros. Haces que sea mucho más fácil para los clientes de API probar y jugar con tu API. ¡Haga que el acceso de solo lectura (que en la mayoría de los casos es la mayor parte del tráfico) sea lo más simple posible!

Pero el dilema de las cadenas de consulta grandes es una limitación válida de GET. Aquí me volvería pragmático, siempre que no alcance este límite, vaya con GET y url-params. Esto funcionará en el 98% de los casos de búsqueda. Solo actúe si alcanza este límite y luego también introduce POST con carga útil (con tipo mime Content-Type: application/x-www-form-urlencoded).

¿Tienes más ejemplos del mundo real?

manuel aldana
fuente
El cálculo fue un ejemplo del mundo real. Acerca de la búsqueda, queremos poder buscar transacciones en múltiples puntos de venta, por lo que abrimos una nueva ventana del navegador para seleccionar los puntos de venta. Y cuando validamos modificamos un parámetro oculto en el formulario de búsqueda para establecer los puntos de venta seleccionados. Si realmente hay muchos de ellos, la solicitud de búsqueda resultante tendrá una cadena de consulta muy larga.
cbliard
4

La confusión en torno a GET es una limitación del navegador. Si está creando una interfaz RESTful para una aplicación A2A o P2P, entonces no hay límite para la duración de su GET.

Ahora, si desea utilizar un navegador para ver su interfaz RESTful (también conocida como durante el desarrollo / depuración), se encontrará con este límite, pero existen herramientas para evitarlo.

ken kranz
fuente
6
"GET es una limitación del navegador", también es una limitación del servidor. Encontrará que todos los servidores web imponen un límite y, si tiene CDN, también pueden imponer un límite. El uso de otras herramientas para realizar la solicitud no eludirá los límites del servidor.
Courtney Miles
0

Esta es una fácil. Utilice POST. HTTP no impone un límite en la longitud de la URL para GET, pero los servidores sí. Sea pragmático y solucione eso con un POST.

También podría usar un cuerpo GET (que está permitido) pero eso es un doble golpe, ya que no es un uso correcto y probablemente tendrá problemas con el servidor.

Rick O'Shea
fuente