Pular para o conteúdo

O que é o método HTTP QUERY

Diagrama comparativo: GET (body ❌, safe ✅), POST (body ✅, safe ❌), QUERY (body ✅, safe ✅)

O método QUERY é uma requisição HTTP que envia a consulta no corpo da request mantendo as garantias de segurança do GET.

QUERY = GET com corpo. Safe, idempotent, cacheable, mas com request body. O problema do POST /search resolvido no nível do protocolo.


RFC 10008, publicada em 15 de junho de 2026. Primeiro método HTTP novo desde PATCH (RFC 5789, 2010). Dezesseis anos sem um método novo.

“A QUERY requests that the request target process the enclosed content in a safe and idempotent manner and then respond with the result of that processing.”

RFC 10008, Section 1

Autores: Julian Reschke (greenbytes), James Snell (Cloudflare), Mike Bishop (Akamai).

A spec começou como SEARCH em 2015. Renomearam em novembro de 2021 para escapar da bagagem do WebDAV. Onze anos do primeiro draft até a publicação.


Propriedade Valor O que significa na prática
Safe Sim Não altera estado no servidor. Proxies e crawlers podem executar sem medo.
Idempotent Sim Repetir a mesma request produz o mesmo resultado. Retry automático é seguro.
Cacheable Sim Respostas podem ser cacheadas. Cache key inclui o body + Content-Type.
Request body Esperado O corpo É a query. Content-Type obrigatório.

O body define a pergunta. O Content-Type define o formato da pergunta. O servidor DEVE rejeitar requests sem Content-Type ou com tipo inconsistente com o conteúdo.

Servidores anunciam suporte com o header Accept-Query:

Accept-Query: application/json, application/graphql

GET POST QUERY
Safe
Idempotent
Cacheable Só para GET/HEAD futuros
Request body Sem semântica definida Esperado Esperado
Retry automático ❌ (pode causar side effects)
Limite prático ~8.000 octetos na URL Sem limite Sem limite
Logs/bookmarks Query vaza em access logs Body não vaza Body não vaza

RFC 9110 recomenda suporte a URIs de pelo menos 8.000 octetos. Isso é um piso, não uma garantia. Cada proxy, load balancer e servidor na cadeia tem seu próprio limite. Você descobre o menor em runtime — geralmente com um 414 atrás de um proxy corporativo que seu test suite nunca vai reproduzir.

URLs também vazam. Access logs, bookmarks, histórico do browser. Se a query tem dados sensíveis, agora estão em todo log do caminho.

POST funciona pra queries. Até você precisar de retry, cache ou semântica honesta.

POST não é safe. POST não é idempotent. Quando a conexão cai no meio da request, nenhum cliente ou proxy sabe se o estado mudou no servidor. Nada faz retry automático. Você acaba construindo idempotency keys na mão — maquinaria que leituras nunca deveriam ter precisado.

Cache? RFC 9110 permite cachear respostas POST só com freshness explícita + Content-Location matching, e mesmo assim só serve GET/HEAD futuros. Duas chamadas POST /search idênticas sempre batem na origin.


  • Filtros complexos que não cabem na URL (JSON com nested objects, arrays, ranges)
  • Queries com dados sensíveis que não devem vazar em logs
  • Endpoints de busca/pesquisa que hoje abusam de POST
  • JSON-RPC e APIs onde toda chamada é semanticamente uma leitura
  • Qualquer read-only request que precisa de body
  • Queries simples que cabem confortavelmente na URL — GET continua sendo melhor (mais simples, universalmente suportado)
  • Operações que alteram estado — use POST/PUT/PATCH/DELETE
  • APIs públicas onde clientes antigos não suportam QUERY — mantenha o POST como fallback
  • Cross-origin em browsers se o preflight OPTIONS é inaceitável para sua latência

A resposta QUERY é cacheable, mas a cache key DEVE incorporar o conteúdo da request, não só a URI. Seção 2.7 da RFC é explícita.

Isso é mais complexo que cachear GET. O cache precisa ler o body inteiro antes de decidir se já viu essa request. Caches podem normalizar (reordenar chaves JSON, remover whitespace) para melhorar hit rate.

O risco: normalização agressiva demais gera falsos positivos — o cache devolve resultado da query errada.

Conditional requests funcionam via ETag e If-None-Match, operando contra o “equivalent resource” — um recurso GET hipotético derivado incorporando o body da request no target.


Terminal window
curl -X QUERY 'http://localhost:3000/contacts' \
-H 'Content-Type: application/json' \
-d '{"filter": {"city": "Berlin"}, "limit": 50}'

O que antes era:

GET /contacts?filter[city]=Berlin&limit=50

Ou, quando ficava grande demais:

Terminal window
POST /contacts/search
Content-Type: application/json
{"filter": {"city": "Berlin", "age_gte": 25, "tags": ["vip", "active"]}, "limit": 50}

Agora tem o método certo: uma leitura que se comporta como leitura.


Stack Status
Node.js Nativo desde Node 21.7.2 / 22+ (llhttp 9.2.0)
Fastify fastify.addHttpMethod('QUERY', { hasBody: true })
Go net/http Funciona com method string arbitrária
.NET .NET 11 Preview 4 reconhece QUERY
Spring PR #34993 aberta, bloqueada
OpenAPI 3.2.0 (set/2025) — campo query nativo
curl -X QUERY com --data e Content-Type explícito
Browsers fetch() aceita, mas CORS preflight obrigatório

CDNs: os autores da RFC trabalham na Cloudflare e Akamai. Bom sinal. Suporte oficial de cache nas edges? Não confirmado ainda.