.NET - Apresentando HATEOAS


Hoje vamos apresentar o conceito de HATEOAS seu funcionamento e para que serve.

O acrônimo HATEOAS é uma abreviação para - Hypermedia as the Engine of Application State - é uma restrição que faz parte da arquitetura REST. Para o ecosistema da plataforma .NET esse conceito esta vinculado às Web APIs.

HATEOAS é um modelo desenvolvido por Leonard Richardson que traz o modelo REST para um novo nível, e cujo objetivo é ajudar os clientes que consomem o serviço REST, ou seja, nossa Web API, a navegar pelos recursos e saber o que podem fazer tornado as ações da WEB API mais fáceis de entender.

Usando uma explicação o mais simples possível, imagine que você faz uma requisição a uma API, e ela vai retornar um objeto ou coleção de objetos como resposta. Essa seria a WEB API sem usar HATEOAS.

Usando HATEOAS a resposta da API acrescenta também links descritivos que servem para informar como você pode alterar o recurso e informações de como buscar recursos secundários ou relacionados.

Entendendo o HATEAOS na prática

Vamos tomar um exemplo bem simples muito comum na vida real.

Uma classe Produto na linguagem C# pode ser representada assim:

public class Produto
 {
        public string Nome { get; set; }
        public string Descricao { get; set; }
        public double Preco { get; set; }
}

A representação JSON desta classe para um retorno de uma requisição GET de um produto específico seria expresso da seguinte forma:

Corpo de um reponse REST para : http://localhost/produto/1

{
  "nome": "Caderno",
  "descricao": "Caderno Espiral 100 folhas",
  "preco": 5.45
}

Este é o padrão de um response da maioria de serviços REST que retornam os dados de um produto.  Temos apenas os dados e nenhuma informação sobre suas conexões ou referências nem como podemos fazer para obter outras informações de produto.

Aqui entra em cena o modelo HATEOAS. Veja abaixo como ficaria uma representação do JSON baseada neste modelo:

{
  "nome": "Caderno",
  "descricao": "Caderno Espiral 100 folhas",
  "preco": 5.45,
  "links" : [{
         "rel" : "self"
         "href" : "http://localhost:8080/produto/1"   
         "method":"GET"      
   }] 
}

A resposta não contém somente os dados do produto, mas inclui uma URL com o endereço de onde as informações dessa produto podem ser localizadas.

Assim poderíamos ter uma resposta com mais informações aplicando o modelo HATEOAS conforme mostrado a seguir:

HATEOAS - Corpo de um reponse REST para : http://localhost/produto/1

{
  "nome": "Caderno",
  "descricao": "Caderno Espiral 100 folhas",
  "preco": 5.45,
  "links" : [{
         "rel" : "self"
         "href" : "http://localhost:8080/produto/1"   
         "method":"GET"      
   },
   "links" : [{
         "rel" : "update_produto"
         "href" : "http://localhost:8080/produto/1"   
         "method":"PUT"      
   },
  "links" : [{
         "rel" : "delete_produto"
         "href" : "http://localhost:8080/produto/1"   
         "method":"DELETE"      
   }] 
}

Dessa forma temos agora não apenas os dados do produto mas também a informação de url para cada recursos fornecendo informações claras sobre como acessar cada recurso.

De acordo com o modelo de maturidade de Richardson, HATEOAS é considerado o ultimo nível do REST. Isto significa que em uma aplicação HATEOAS presume-se que os verbos padrão de uma aplicação REST como GET, POST, PUT e DELETE também são adotados. Sendo que cada um deles, como é mostrado acima, provê ao cliente os links necessários ao acesso à uma informação.

De uma forma bem simples com HATEOAS cada Body response fornece, além dos dados, links com respostas para perguntas do tipo : "E agora ? o que eu posso fazer depois ?" , pois você terá o objeto encapsulado na propriedade "value" e a navegação na matriz "links".

Uma forma de fazer a implementação do modelo HATEOAS na ASP .NET Core é usar uma classe Helper que utiliza generics para envolver o tipo com o qual você esta tratando. Exemplo:

public class Link
{
    public string Href { get; set; }
    public string Rel { get; set; }
    public string method { get; set; }
}
public class LinkHelper<T> where T: class 
{
    public T Value { get; set; }
    public List<Link> Links { get; set;}
    public LinkHelper()
    {
        Links = new List<Link>();
    }
    public LinkHelper(T item) : base()
    {
        Value = item;
        Links = new List<Link>();
    }
}

E estamos conversados...

Para mais informações sobre as especificações do HATEOAS visite : https://restfulapi.net/hateoas/

Para ver uma implementação do Hateoas veja este artigo: ASP .NET Core - Implementando HATEOAS

Referências:


José Carlos Macoratti