HATEOAS - VOCÊ REALMENTE CONHECE REST?
O REST ou Representational State Transfer é um estilo de arquitetura que provê um padrão de comunicação entre diferentes sistemas na web, ele foi feito para ser simples, muitos desenvolvedores já usaram REST nas suas aplicações, tanto desenvolvedores front-end quanto os back-end tem contato com o padrão REST de comunicação. Tá, você já usou REST várias vezes, fez várias API's, consumiu dados de várias outras, GET, POST, PUT, DELETE e blá blá blá, mas em que ponto da sua carreira você descobriu que o REST é muito mais do que só usar os verbos HTTP certos? (não que usar os verbos certos não seja importante, é importante!) O REST possui níveis de maturidade e uma "boa API" seguindo esse padrão(REST) precisa de algumas coisas que infelizmente ainda são raras de encontrar nas API's dos desenvolvedores que estão começando.
Nesse conteúdo o meu objetivo é te mostrar os níveis de maturidade do REST e como você pode desenvolver melhores API's conhecendo esses níveis de maturidade, eu acredito que esse conhecimento pode te destacar no mercado, então se você acha que esse conteúdo pode agregar alguma coisa na sua carreira ou conhecimento é só seguir comigo para que a gente possa entender esses fundamentos juntos, pega o seu café, a gente tem um conteúdo bacana pra ver a partir daqui.
Curiosidade rápida: Sabe porque quando trabalhamos com REST precisamos passar tokens de autenticação em toda requisição que fazemos quando estamos trabalhando com rotas privadas ou que precisam de autenticação, por exemplo? Porque o REST funciona de forma Stateless
, isso quer dizer que não armazenamos qualquer informação sobre transações passadas, toda transação que fazemos é feita como se fosse a primeira vez.
Richardson Maturity Model
O Richardson Maturity Model é um modelo que classifica API's web baseado em quatro níveis de maturidade, cada um desses níveis possuem características que tornam uma API que usa o padrão REST mais madura, podemos ver esse modelo como o nível 0 sendo o mais básico e o nível 4 sendo o nível ideal para uma boa API, vamos perceber que a maiorias dos desenvolvedores vão até o nível de maturidade dois no desenvolvimento de suas API's.
Esse modelo divide em três as principais partes que um modelo de comunicação REST deve ter, elas são:
- Resource identification;
- HTTP Verbs;
- HATEOAS (Hypermedia as the Engine of Application State);
Como vimos, o RMM (Richardson Maturity Model) possui quatro níveis de maturidade, sendo que o nível 0 leva em consideração que você não está seguindo nenhum tipo de padronização, e os outros níveis são os que vimos acima, vamos entender cada um deles agora.
Nível 1 - Resources identification
Aqui não temos nada complexo de entender, o nível um de maturidade leva em conta que você padronize sua URI utilizando substantivos para que ela fique coerente, supondo que temos uma API que trabalha com users o nível um de maturidade seriam termos nossa URI dessa forma:
Verbo | Type |
---|---|
GET |
/users/1 |
POST |
/users |
DELETE |
/users/1 |
PUT |
/users/1 |
PATCH |
/users/1 |
Como eu disse, nade de complexo, na verdade esse geralmente é o padrão comum que encontramos nas URI de uma API, se você ainda não usa esse tipo de padrão, já passou da hora de começar.
Nível 2 - HTTP Verbs
Aqui nós também não temos nada de novo, como eu comentei inicialmente, usar os verbos HTTP corretos é importante, tanto que o nível dois de maturidade se trata exatamente disso, usar corretamente os verbos HTTP nas suas requisições, como também mencionei anteriormente, a maioria dos desenvolvedores vem até este nível de maturidade com o REST e geralmente desconhecem o próximo nível.
Nível 3 - HATEOAS
Nesse nível de maturidade nossa API vai responder nosso endpoint informando quais outras operações nós ainda podemos fazer, isso ajuda na auto documentação da nossa API e também na usabilidade dela, veja um exemplo de resposta utilizando esse nível de maturidade:
// GET - http://localhost:80/users/1
{
user: {
"id": 1,
"name": "John Doe",
"email": "johndoe@johndoe.com"
},
links: [
{
"type": "GET",
"rel": "self",
"uri": "http://localhost:80/users/1"
},
{
"type": "DELETE",
"rel": "delete_user",
"rel": "http://localhost:80/users/1"
},
{
"type": "GET",
"rel": "root_informations",
"uri": "http://localhost:80/users/1/root"
}
]
}
Perceba que ao fazer uma requisição em um usuário específico a nossa API nós retorna também diversos links relacionados com novas ações que podem ser feitas.
Quanto maior o nível que alcançamos com os recursos da nossa API mais madura ela é considerada, poucos devs se atentam ao nível três de maturidade baseado no RMM, mas seja sincero, sempre que você precisa utilizar API's externas, não seria bem mais fácil utilizar elas se elas tivessem até o nível três de maturidade?
OBS: Seguir esse padrão não é algo extremamente importante e você não precisa ficar "pirado" com isso, apesar de ser uma boa prática você precisa lembrar que existem contextos que talvez ela não seja interessante ou que existam melhores soluções.
Bônus - HTTP Method Negotiation
O HTTP possui ainda mais um método, que é pouco conhecido e pouco utilizado, esse método é o OPTIONS
, ele nos permite informar quais métodos são permitidos em determinado endpoints da nossa API, por exemplo, podemos mandar uma request com o método OPTIONS
para a URL de exemplo "http://localhost:80/posts"
Fazendo essa requisição nossa API deve devolver no cabeçalho da resposta algo do tipo:
HTTP/1.1 200 OK
Allow: GET, POST
Caso qualquer outro método seja enviado para esse endpoint tentando realizar alguma ação deve receber uma resposta mais ou menos assim:
HTTP/1.1 405 Not allowed
Allow: GET, POST
Parte 2?
Existem alguns pontos muito interessante do REST que poucos desenvolvedores conhecem e utilizam, pontos como: HAL, Content Negotiation, Content-Type Negotiation, a forma correta de retornar um erro... São quase como dicas pontuais que te ajudam a melhorar bastante a qualidade da sua API e te diferenciar do restante do mercado.
Futuramente pretendo desenvolver uma parte dois desse conteúdo caso vocês leitores julguem relevante.
Eu espero do fundo do meu coração ter ajudado nem que seja um pouquinho no seu aprendizado sobre REST e te dado alguns pontos interessantes para poder evoluir na sua carreira.
Viva a jornada! ⏳
Até a próxima.
Um padrão simples mas que nem sempre está presente é de retornar no body da requisição, especilamente em paginações, informações como total de elementos, total por página, url da próxima página, url da página anterior, número da página atual e outras informações relevantes que ajudam na depuração e informação da api. Tratamento de errors também é outra coisa que muitas APIs falham em lidar, as vezes retornando logs/stacktrace do servidor, não informando erros com mensagens significativas, ou seja, coisas básicas que todo desenvolvedor deveria prezar!
Na minha opinião, HATEOAS é um downgrade, se você realmente precisa implementar isso, é um sinal que a sua documentação é péssima! Só adiciona mais trabalho e boiler plate no retorno das suas rotas e no fundo é só um detalhe que ninguem vai ver ou se importar porque a maioria das pessoas vão usar wrappers de apis que abstraem tudo de qualquer maneira.