Método HTTP QUERY: guía completa, ventajas y seguridad
Introducción
El método HTTP QUERY es una propuesta/convención para resolver una necesidad común en APIs: realizar operaciones de lectura complejas que requieren un cuerpo de petición (payload) sin sacrificar las propiedades de seguridad, idempotencia y caché esperables de los métodos seguros como GET. En esta guía explico su semántica, ventajas, riesgos de seguridad, ejemplos prácticos y recomendaciones de implementación y despliegue.
¿Qué es el método HTTP QUERY?
QUERY es un método HTTP pensado para consultas (read-only) que:
- Son seguras (no deben producir efectos secundarios en el servidor).
- Son idempotentes (repetir la misma petición no cambia el estado del servidor).
- Aceptan un cuerpo en la petición (por ejemplo, filtros complejos en JSON).
- Mantienen comportamiento predecible para cacheo y proxies cuando se usan correctamente.
El objetivo es cubrir el hueco entre GET (que no admite body de forma fiable y está limitado por la longitud de URL) y POST (que admite body pero suele tratarse como no cachéable y no necesariamente idempotente).
Semántica y convenciones recomendadas
- Semántica: QUERY = operación de lectura compleja. No debe modificar recursos.
- Body: permitido y normalmente en application/json o application/merge-patch+json según el uso.
- Cabeceras relevantes: Content-Type, Content-Length, Cache-Control, Vary, Authorization, If-Modified-Since, If-None-Match.
- Respuestas cachéables si incluyen cabeceras de cacheo válidas (Cache-Control, Expires) y no contienen datos sensibles sin protección.
- Status típicos: 200 OK (con cuerpo), 204 No Content, 304 Not Modified, 400 Bad Request, 404 Not Found, 405 Method Not Allowed, 415 Unsupported Media Type, 422 Unprocessable Entity.
Comparación con GET y POST
- GET
- Pros: naturalmente cachéable, seguro (según definición), simple.
- Contras: no acepta body de forma fiable, URL limitada en longitud, filtros complejos difíciles en query string.
- POST
- Pros: admite body con cualquier formato.
- Contras: por defecto no es cachéable, no es semánticamente seguro/idempotente, puede causar confusión entre lecturas y escrituras.
- QUERY
- Pros: pensado explícitamente para lecturas con body; mantiene semántica de "solo lectura" y puede ser cachéable si se diseña así.
- Contras: no es un método HTTP estándar ampliamente soportado por todos los proxies/infra; puede requerir configuración extra en servidores y proxies; comportamiento frente a navegadores y CORS puede implicar preflight.
Caché y claves de caché
Para que un proxy o CDN cachee respuestas a peticiones QUERY debes:
- Asegurar que la respuesta incluya Cache-Control (por ejemplo, Cache-Control: public, max-age=60).
- Definir qué elementos forman la clave de caché. Dado que QUERY usa body, la clave debe incluir:
- Método (QUERY)
- URL (path + host)
- Representación del body (por ejemplo, un hash/digest del body)
- Cabeceras relevantes (por ejemplo, Authorization, Accept-Language)
Recomendación práctica: incluir un header con digest del body:
Digest: sha-256=Base64(SHA256(body))
y configurar el proxy para que incluya ese header en la clave de caché.
Si la respuesta es por usuario (contenidos privados), usar Cache-Control: private o evitar cacheo en proxies compartidos.
Seguridad: riesgos y mitigaciones
Riesgos principales:
- Exposición de datos en caches compartidos (si la respuesta incluye datos sensibles).
- CSRF y CORS: al ser un método no estándar, los navegadores harán probablemente CORS preflight (OPTIONS) para peticiones cross-origin; eso reduce el riesgo de CSRF en la práctica, pero no lo elimina por completo en escenarios mal configurados.
- Inyección (SQL, NoSQL, LDAP) a través de filtros complejos en el body.
- Denegación de servicio por cuerpos muy grandes o consultas costosas.
- Fuga de información en logs o traces si el body contiene datos sensibles.
Mitigaciones:
- Requerir TLS (HTTPS) siempre.
- Autenticación basada en tokens (Authorization: Bearer ...) en vez de cookies para evitar ciertos vectores de CSRF; si se usan cookies, aplicar SameSite=strict/lax y CSRF tokens cuando corresponda.
- Para respuestas con datos por usuario, marcar Cache-Control: private o añadir Vary: Authorization; evitar que proxies públicos cacheen respuestas privadas.
- Validar y sanitizar todos los parámetros del body en el servidor. Rechazar shapes inesperados.
- Limitar tamaño del body en el servidor (por ejemplo, 64 KB / 256 KB según caso).
- Imponer límites de coste computacional y timeouts para consultas (circuit-breaker / queueing).
- No registrar cuerpos completos en logs; en su lugar registrar hashes/digests o redacted bodies.
- Implementar rate limiting por cliente / IP / API key.
Headers y control de caché aconsejados
- Cache-Control: public, max-age=60 (si es caché público)
- Cache-Control: private, max-age=60 (si es por usuario)
- Vary: Authorization, Accept-Language (según corresponda)
- ETag + If-None-Match para soporte de 304 Not Modified
- Digest del body en petición para clave de caché
- Content-Type: application/json para cuerpos JSON
Ejemplos prácticos
Ejemplo de petición con curl:
curl -X QUERY
-H "Content-Type: application/json"
-H "Authorization: Bearer
-d '{"filter":{"status":"open","tags":["bug","urgent"]},"sort":["-created_at"],"page":1,"per_page":20}'
https://api.ejemplo.com/issues/search
Ejemplo de respuesta:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private, max-age=30
ETag: "abc123"
Vary: Authorization
{
"total": 42,
"page": 1,
"per_page": 20,
"results": [
{"id": 123, "title": "Error en login", "status":"open"},
...
]
}
Ejemplo de manejo en Node (Express):
// Express no tiene app.query por defecto; usa app.all o app.use y filtra por método.
app.all('/issues/search', (req, res) => {
if (req.method !== 'QUERY') {
return res.status(405).send('Method Not Allowed');
}
// parsear body (express.json middleware)
const filters = req.body;
// validar filtros...
// ejecutar consulta y devolver resultados (sin modificar estado)
res.json({ total: 42, page: 1, per_page: 20, results: [] });
});
Ejemplo de nginx (permitir método y proxy pass):
# nginx por defecto pasa métodos arbitrarios, pero si usas limit_except
location / {
limit_except GET POST QUERY {
deny all;
}
proxy_pass http://backend;
}
Consideraciones de compatibilidad y despliegue
- Proxies, WAF y CDNs: algunos intermediarios pueden bloquear o no reconocer métodos no estándar. Antes de producir, verificar compatibilidad con CDN/proxy/WAF (Cloudflare, Fastly, AWS ALB, etc.) y añadir reglas si es necesario.
- CORS: los navegadores harán preflight para métodos no simples; asegurar que el servidor responde correctamente a OPTIONS y declara Access-Control-Allow-Methods: QUERY, Access-Control-Allow-Headers: Content-Type, Authorization, Digest.
- Documentación del API: dejar claro que QUERY es "read-only" y describir la semántica exacta, ejemplos y cabeceras relevantes.
- Migración: para APIs ya existentes que usan POST para búsquedas, ofrecer soporte dual (POST y QUERY) durante una transición y documentar diferencias de caché y semántica.
Buenas prácticas y recomendaciones finales
- Define y documenta la semántica del método en tu API (qué se considera “seguro” y “sin efectos secundarios”).
- Usa Authorization con tokens y evita cacheo público de respuestas privadas.
- Normaliza cómo se construye la clave de caché (incluir digest del body si el body influye en la respuesta).
- Limita tamaño del body y coste de las consultas; aplica timeouts.
- Asegura logs y telemetría sin exponer datos sensibles (guardar digests).
- Prueba con tu CDN/proxy y entornos de seguridad antes de lanzar.
- Si la compatibilidad con intermediarios es un problema, considera alternativas: POST con cabeceras y cache-control explícito, o usar endpoints de búsqueda con parámetros paginados y reducción de complejidad en query string.
Conclusión
El método HTTP QUERY puede ser una solución elegante para separar conceptos: operaciones de lectura complejas que necesitan body, manteniendo propiedades de seguridad e idempotencia. Su principal ventaja es permitir cuerpos ricos en consultas sin perder la posibilidad de un cacheo correcto y predecible. Sin embargo, introducir un método no estándar requiere planear la compatibilidad con proxies/CDN, proteger contra exposición de datos en caches, y garantizar validación y límites en el servidor. Si decides adoptarlo, documenta claramente la semántica, diseña las claves de caché y aplica las mitigaciones de seguridad descritas.

