Conceito e implementação de HATEOAS
ResumoHATEOAS (Hypermedia as the Engine of Application State) é o nível 3 de maturidade REST: a resposta inclui links que dizem ao cliente quais ações são possíveis. Implementamos links com media types customizados.
1. Objetivos de Aprendizagem#
- Explicar o que é HATEOAS e por que importa.
- Modelar links (
href,rel,method). - Implementar HATEOAS condicionado a um media type customizado.
2. Pré-requisitos#
- Data shaping (Módulo 34) e content negotiation (Módulo 21).
3. Conceito#
Numa API HATEOAS, cada recurso traz hypermedia: links para operações relacionadas (self, próxima página, deletar). O porquê: o cliente navega pela API seguindo links, em vez de codificar URLs — reduzindo acoplamento. Um link tem:
{ "href": "/api/produtos/1", "rel": "self", "method": "GET" }
Como HATEOAS muda o formato da resposta, ativamos via media type customizado (application/vnd.catalog.hateoas+json), preservando clientes que não o pedem.
4. Mão na Massa#
4.1. Setup#
Registre o media type customizado nas opções do MVC (ver tópico do Root Document, Módulo 36, para o filtro de validação de media type).
4.2. Implementação Passo a Passo#
- Modelos de link:
public record Link(string? Href, string Rel, string Method);
public class LinkResourceWrapper<T>
{
public List<T> Value { get; set; } = new();
public List<Link> Links { get; set; } = new();
}
- Gerador de links (usa
LinkGenerator):
public class ProdutoLinks
{
private readonly LinkGenerator _linkGenerator;
public ProdutoLinks(LinkGenerator linkGenerator) => _linkGenerator = linkGenerator;
public List<Link> CreateForProduto(HttpContext http, Guid categoriaId, Guid id) => new()
{
new(_linkGenerator.GetUriByAction(http, "GetProduto",
values: new { categoriaId, id }), "self", "GET"),
new(_linkGenerator.GetUriByAction(http, "Deletar",
values: new { categoriaId, id }), "delete_produto", "DELETE"),
};
}
- Ativação condicional pelo
Accept:
var incluiLinks = http.Request.Headers.Accept
.ToString().Contains("vnd.catalog.hateoas", StringComparison.OrdinalIgnoreCase);
4.3. Executando#
curl -H "Accept: application/vnd.catalog.hateoas+json" \
http://localhost:5000/api/categorias/{catId}/produtos
A resposta passa a incluir links por item e na coleção.
5. Exemplo Completo#
Resposta típica com HATEOAS:
{
"value": [
{ "id": "1", "nome": "Mouse", "links": [
{ "href": "/api/.../produtos/1", "rel": "self", "method": "GET" },
{ "href": "/api/.../produtos/1", "rel": "delete_produto", "method": "DELETE" }
]}
],
"links": [
{ "href": "/api/.../produtos", "rel": "self", "method": "GET" }
]
}
6. Boas Práticas e Armadilhas#
| Faça | Evite |
|---|---|
Gerar URLs com LinkGenerator (rotas nomeadas) | Concatenar strings para montar links |
| Ativar HATEOAS por media type customizado | Quebrar clientes existentes forçando o novo formato |
Incluir rel e method claros | Links sem semântica de ação |
AtençãoHATEOAS adiciona complexidade e payload. Avalie se seus consumidores realmente navegam por links — muitos clientes ignoram hypermedia. É uma decisão de tradeoff, não obrigatória.
7. Segurança e Produção#
- Gere apenas links para ações que o usuário pode executar (respeite autorização), evitando expor operações não permitidas.
8. Exercícios#
- Fácil: adicione um link
update_produto(PUT). - Médio: inclua links de paginação (
next/previous) na coleção. - Desafio: condicione os links às permissões do usuário autenticado.
9. Resumo#
HATEOAS enriquece respostas com links de ações, ativado por media type customizado para não quebrar clientes. LinkGenerator produz URLs confiáveis a partir das rotas nomeadas.
10. Próximos Passos#
Módulo 36: métodos OPTIONS e HEAD.
11. Referências#
- Microsoft Learn — LinkGenerator
- Microsoft Learn — Formatação e media types
- Richardson Maturity Model — Níveis de maturidade REST