Pular para o conteúdo

Antes e Depois

Antes: POST tangled e GET com URL overflow. Depois: QUERY limpo e direto.

Código fala mais que texto. Cada bloco abaixo mostra o mesmo resultado — a diferença é o que você comunica à infraestrutura HTTP.


# Você está MENTINDO para a infraestrutura HTTP.
POST /api/employees/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"department": "engineering",
"skills": ["typescript", "rust"],
"experience_min": 3,
"location": "remote",
"active": true
}
# QUERY é safe + idempotent + cacheable.
# Proxies podem cachear. Clients podem fazer retry automático.
QUERY /api/employees HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
{
"department": "engineering",
"skills": ["typescript", "rust"],
"experience_min": 3,
"location": "remote",
"active": true
}

A resposta do servidor é idêntica. O que muda é o contrato semântico.


# GraphQL usa POST para TUDO — queries e mutations.
# Resultado: zero caching HTTP nativo para reads.
POST /graphql HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"query": "query GetUser($id: ID!) { user(id: $id) { name email avatar posts { title } } }",
"variables": { "id": "usr_42" }
}
# Agora a infraestrutura HTTP sabe que isso é read-only.
# Retry automático em falha de conexão.
QUERY /graphql HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
{
"query": "query GetUser($id: ID!) { user(id: $id) { name email avatar posts { title } } }",
"variables": { "id": "usr_42" }
}

GraphQL é o maior beneficiário imediato. Queries finalmente podem ser cacheadas no nível HTTP sem hacks.


# Elasticsearch sempre usou POST para buscas.
# Cada poll de dashboard = request completo ao origin.
POST /products/_search HTTP/1.1
Host: elasticsearch.internal:9200
Content-Type: application/json
{
"query": {
"bool": {
"must": [
{ "match": { "category": "electronics" } },
{ "range": { "price": { "gte": 100, "lte": 500 } } }
],
"filter": [
{ "term": { "in_stock": true } }
]
}
},
"sort": [{ "price": "asc" }],
"size": 20
}
# Mesmo DSL. Mesma resposta. Semântica correta.
# Um retry depois de timeout é seguro por definição.
QUERY /products/_search HTTP/1.1
Host: elasticsearch.internal:9200
Content-Type: application/json
{
"query": {
"bool": {
"must": [
{ "match": { "category": "electronics" } },
{ "range": { "price": { "gte": 100, "lte": 500 } } }
],
"filter": [
{ "term": { "in_stock": true } }
]
}
},
"sort": [{ "price": "asc" }],
"size": 20
}

Imagine dashboards de monitoramento fazendo polling: cada QUERY idêntica pode ser servida do cache.


# Tudo no URL. Limites variam por proxy (2KB? 8KB?).
# Logs expostos. Bookmarks quebrados. 414 surpresa em produção.
GET /api/reports?start_date=2026-01-01&end_date=2026-06-30&metrics=revenue,churn,mrr,arr,ltv,cac&group_by=month&filters[region]=latam&filters[plan]=pro,enterprise&filters[team_size]=50-200&include=comparison_period&comparison_start=2025-01-01&comparison_end=2025-06-30&format=detailed&currency=BRL HTTP/1.1
Host: api.example.com
# Query no corpo. URL limpa. Sem limites de tamanho.
QUERY /api/reports HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json
{
"period": {
"start": "2026-01-01",
"end": "2026-06-30"
},
"metrics": ["revenue", "churn", "mrr", "arr", "ltv", "cac"],
"group_by": "month",
"filters": {
"region": "latam",
"plan": ["pro", "enterprise"],
"team_size": "50-200"
},
"comparison": {
"start": "2025-01-01",
"end": "2025-06-30"
},
"format": "detailed",
"currency": "BRL"
}

URLs não vazam em logs de acesso. Filtros complexos ficam estruturados. Acabou o terror do 414 URI Too Long.


Aspecto POST (antes) QUERY (depois)
Retry automático em falha ❌ Unsafe — pode duplicar side effects ✅ Idempotent — retry seguro
Cache HTTP nativo ❌ Caches ignoram POST ✅ Cacheable por URI + body
Semântica correta ❌ “Crie algo” usado para “leia algo” ✅ “Estou perguntando”
Preflight CORS Depende do Content-Type Sim (QUERY não é safelisted)
Accept-Query discovery ✅ Servidor anuncia formatos aceitos
# Conexão caiu no meio da resposta?
POST /search → Client não sabe se o servidor processou. Não faz retry.
QUERY /search → Client refaz automaticamente. Garantia de spec: sem side effects.
# Duas chamadas idênticas em 10 segundos:
POST /search → 2x origin hit. Sempre.
QUERY /search → 2ª servida do cache (se response tem freshness headers).

  • Response format — JSON, XML, o que for. A resposta é a mesma.
  • Status codes200, 404, 400, 500 funcionam igual.
  • Error handling — Mesma lógica de validação e tratamento de erros.
  • Authentication — Bearer tokens, API keys, cookies — tudo igual.
  • Content negotiationAccept header funciona normalmente.
  • Corpo da requisição — Mesmo JSON, mesmo schema, mesma validação.

A única diferença no wire é a primeira linha: QUERY no lugar de POST ou GET.


Quer ver código rodando em Node.js, Go, Python e curl?

Veja implementações reais