O que é o novo método HTTP QUERY

O .NET 10 esta introduzindo suporte nativo ao método HTTP QUERY, um novo verbo padronizado pelo IETF que preenche uma lacuna histórica no desenvolvimento de APIs. O problema que o QUERY resolve e simples: como fazer uma requisição de busca com um body JSON rico quando você não pode usar POST (semanticamente errado para buscas) nem GET (que não suporta body na prática)?

Por anos, devs que precisavam enviar filtros complexos em requisições de busca usaram workarounds: POST para um endpoint /search, GET com querystrings longas que frequentemente ultrapassavam o limite de 414 (Request-URI Too Long), ou extensões proprietárias. O método QUERY padroniza esse caso de uso com a semântica correta: uma operação de leitura idempotente que pode carregar um body com critérios de filtro.

O artigo que motivou esta publicação descreveu exatamente o problema: uma API com 600 filtros possíveis que gerava erros 414 frequentes quando devs tentavam usar GET com querystring para transmitir combinações de filtros. O QUERY resolve isso de forma elegante e padrão.

Como funciona o método QUERY

O método QUERY se comporta como GET em termos de semântica: e idempotente, pode ser cacheado e não tem efeitos colaterais. A diferença e que, como POST, suporta um body na requisição. Isso permite enviar critérios de busca complexos em formato JSON ou XML sem as limitações do tamanho de URL.

A especificação do IETF define que respostas a QUERY podem ser cacheadas (diferente de POST), o que é crucial para performance em APIs de busca pesadas. O servidor pode retornar headers Cache-Control normais e o cliente ou proxies podem armazenar o resultado.

No .NET 10, o suporte foi adicionado ao ASP.NET Core de forma transparente. Você pode mapear handlers para o método QUERY da mesma forma que faz para GET, POST, PUT e outros verbos já suportados.

💡
Dica

O método QUERY e particularmente útil quando você tem critérios de busca complexos com estrutura aninhada que não cabem facilmente em querystring. Se seus filtros são simples (2-3 parâmetros), GET com querystring ainda e a abordagem mais compatível com navegadores e clientes simples.

Principais recursos do suporte no .NET 10

O ASP.NET Core no .NET 10 adiciona suporte ao QUERY em três camadas:

  • Minimal APIs: novo método de extensão MapQuery no RouteGroupBuilder e na aplicação, análogo ao MapGet, MapPost, etc.
  • MVC Controllers: novo atributo [HttpQuery] para decorar actions, similar ao [HttpGet] e [HttpPost] existentes.
  • Model binding: o body da requisição QUERY e lido e vinculado automaticamente via model binding, exatamente como POST/PUT.

A implementação no .NET 10 também adiciona suporte ao QUERY no cliente HTTP (HttpClient), permitindo fazer requisições QUERY com body de forma nativa sem workarounds.

Como usar: exemplos de código

Para Minimal APIs, o uso e direto:

// Program.cs - .NET 10 Minimal API
app.MapQuery("/api/produtos/busca", async (
    [FromBody] ProdutoFiltro filtro,
    IProdutoService service) =>
{
    var resultados = await service.BuscarAsync(filtro);
    return Results.Ok(resultados);
});

// Modelo de filtro rico
public record ProdutoFiltro(
    string? Nome,
    decimal? PrecoMinimo,
    decimal? PrecoMaximo,
    IEnumerable<string> Categorias,
    bool? ApenasEstoque,
    int Página = 1,
    int TamanhoPagina = 20
);

Para MVC Controllers:

[ApiController]
[Route("api/[controller]")]
public class ProdutosController : ControllerBase
{
    [HttpQuery("busca")]
    public async Task<IActionResult> Buscar(
        [FromBody] ProdutoFiltro filtro)
    {
        var resultados = await _service.BuscarAsync(filtro);
        return Ok(resultados);
    }
}

No cliente (HttpClient), a requisição QUERY com body:

// HttpClient no .NET 10
var filtro = new ProdutoFiltro(
    Nome: "notebook",
    PrecoMinimo: 2000,
    Categorias: ["eletrónicos", "informática"]
);

var response = await httpClient.QueryAsync(
    "/api/produtos/busca",
    JsonContent.Create(filtro)
);

var produtos = await response.Content
    .ReadFromJsonAsync<List<Produto>>();
⚠️
Atenção

O método QUERY ainda não e suportado nativamente por todos os navegadores e algumas ferramentas de API como o Postman podem precisar de atualização. Verifique compatibilidade antes de usar em APIs públicas consumidas por browsers diretamente.

O problema do 414 resolvido

O caso de uso que ficou famoso no Dev.to e exatamente o cenário de 600 filtros: uma API de busca de produtos com centenas de parâmetros possíveis. Com GET, querystrings como:

GET /api/produtos?categoria=eletrónicos&marca=Samsung&marca=LG&cor=preto&cor=branco&...
# 600 filtros = URL de vários kilobytes
# Resultado: HTTP 414 Request-URI Too Long

Com QUERY, a mesma busca fica limpa e sem limitação de tamanho:

QUERY /api/produtos/busca
Content-Type: application/json

{
  "categorias": ["eletrónicos"],
  "marcas": ["Samsung", "LG"],
  "cores": ["preto", "branco"],
  "... mais 596 filtros sem problema de tamanho ..."
}

Comparação com alternativas existentes

Antes do QUERY, as principais alternativas eram:

POST para /search: funcionava, mas semanticamente errado. POST implica criação de recurso. Caches não armazenam POST. Não ha garantia de idempotência.

GET com querystring: correto semanticamente para busca. Limitado em tamanho (variável por servidor, tipicamente entre 2KB e 8KB). Não suporta estrutura aninhada facilmente.

GET com header customizado: alguns devs colocavam o JSON do filtro em um header HTTP customizado. Tecnicamente funciona, mas e um hack e viola o contrato do protocolo.

O QUERY e a solução padrão que resolve todos esses problemas mantendo a semântica correta de uma operação de leitura.

Pontos positivos e limitações

Pontos positivos: semanticamente correto, suporta body rico, pode ser cacheado, idempotente, e uma spec do IETF (não proprietário) e o suporte nativo no .NET 10 facilita a adoção.

Limitações: compatibilidade de clientes e o maior obstáculo. Navegadores web não suportam o método QUERY em fetch/XMLHttpRequest nativamente ainda. Ferramentas antigas de API testing podem precisar de atualização. Para APIs públicas consumidas por browsers diretamente, POST para /search ainda pode ser mais seguro no curto prazo.

🔴
Cuidado

Proxies, load balancers e WAFs mais antigos podem rejeitar ou não encaminhar o método QUERY corretamente. Teste seu ambiente de infraestrutura antes de colocar em produção. Um WAF que bloqueia métodos HTTP desconhecidos vai barrar requisições QUERY.

Casos de uso reais

APIs de busca interna: sistemas enterprise com critérios de busca complexos onde você controla o cliente e a infraestrutura são o caso de uso ideal para QUERY.

Microsservicos: comunicação entre microsservicos onde você controla ambas as pontas e pode garantir suporte ao QUERY em ambos.

GraphQL-like queries em REST: APIs que querem oferecer flexibilidade de query ao estilo GraphQL sem adotar a spec completa do GraphQL.

Relatórios com filtros ricos: endpoints de relatório onde o usuário pode combinar dezenas de dimensões e métricas em uma única requisição.

Dicas e boas práticas

💡
Dica

Adicione validação de tamanho de body nas requisições QUERY, assim como faz em POST. Um filtro com 600 campos e valido, mas um body de 10MB provavelmente indica uso incorreto ou tentativa de abuso.

🚀
Pro tip

Configure cabeçalhos de cache na resposta QUERY para aproveitar a capacidade de caching do método. Um endpoint de busca de produtos que é cacheavel por 60 segundos pode reduzir drasticamente a carga no banco de dados em picos de acesso.

💡
Dica

Documente explicitamente no Swagger/OpenAPI que o endpoint usa QUERY. A especificação OpenAPI 3.1 não tem suporte nativo para QUERY ainda, mas você pode usar extensões para descrever o método.

O erro mais comum ao adotar QUERY e assumir que toda a infraestrutura suporta sem verificar. Teste o caminho completo: cliente, proxy reverso, load balancer, WAF, e servidor antes de habilitar em produção.

Vale a pena adotar no .NET 10?

Para APIs internas onde você controla cliente e servidor: sim, e uma solução muito mais elegante do que os workarounds existentes. A semântica correta de operação de leitura cacheavel e um beneficio real, especialmente em sistemas com carga alta.

Para APIs públicas consumidas por browsers: aguarde melhor suporte nos browsers antes de migrar. POST para /search ainda e a abordagem mais segura para esse caso.

O próximo passo para quem usa .NET: instale o preview do .NET 10, experimente o MapQuery ou HttpQuery em um projeto de teste e avalie se faz sentido para o seu caso de uso específico. A migração de POST /search para QUERY e simples quando você tem controle de ambos os lados.