API HTTP, REST ou RESTFul

O post desvela não apenas uma metodologia técnica, mas uma visão filosófica sobre a construção de sistemas distribuídos. Os princípios fundamentais de transferência de estado, a linguagem universal do HTTP e a aplicação do conceito HATEOAS não apenas conectam sistemas, mas redefinem a própria essência da interconectividade digital. Além disso, o Modelo de Maturidade de Richardson oferece uma bússola, que embora questionável ela é didática, guiando as implementações.

O artigo API HTTP, REST ou RESTFul é uma exploração profunda no universo das APIs REST, desvendando desde dos conceitos básicos aos avançadas. A compreensão destes princípios não apenas aprimora a expertise técnica, mas também redefine a forma como concebemos e implementamos interações entre sistemas distribuídos.

Assim, ao longo desta postagem, exploraremos a importância do HTTP como fundação das APIs, entenderemos os princípios fundamentais do REST, mergulharemos no conceito de HATEOAS (Hypermedia As The Engine Of Application State) e examinaremos o Modelo de Maturidade de Richardson.

Então, nos preparando para este aprofundamento, é crucial compreender não apenas o “o quê” e o “como” das APIs REST, mas também o “porquê”. Afinal, em um mundo cada vez mais interligado, a habilidade de criar, entender e aprimorar APIs REST torna-se uma habilidade indispensável para os profissionais de tecnologia da informação.

Aqui no blog temos diversos artigos sobre desenvolvimento, apis, devops, kubernetes, domain driven design e afins. Veja alguns artigos interessantes, embora não sejam obrigatórios, para essa temática em especial:

API – Application Programming Interface

O útimo post publicado aqui no blog é o Porque você precisa saber HTTP. Não é exatamente obrigatório, mas é fundamental saber bem HTTP, seja você profissional de desenvolvimento, operações, dados, etc. Pois bem, fique a vontade para consultar mais detalhes sobre o assunto, caso prefira.

API ou Application Programming Interface (Interface de programação de aplicações) integra sistemas ao expor parte de suas funções através de encapsulamentos (Ainda que não participem diretamente do bloco de código da API em questão). Então, quando sua aplicação cria um arquivo texto no disco rígido ela acessa uma API para tal. Desse modo, normalmente utiliza-se algum framework que encapsula funções do sistema operacional responsável por interagir com o driver do HD. Entretanto são poucos os desenvolvedores que precisam dominar isso no detalhe.

Então, o que quero dizer com tudo isso é que API não é algo exclusivo de aplicações web utilizando protocolos como HTTP, GraphQL etc. Mas é verdade que há muitas delas construídas para acesso distrubuído utilizando HTTP como protocolo. Isso se dá, especialmente, pela versatilidade do HTTP e pela grade adesão que ele ganhou desde sua origem.

API HTTP – HyperText Transfer Protocol

As APIs HTTP nada mais são do que sockets abertos no lado do servidor web esperando por requisições qualificadas. Esse protocolo trabalha com conceitos particulares chamados request (detalhes do que se deseja), response (resposta do pedido realizado), resource (identificação do item desejado) e verb/method (ação desejada com o recurso). Quando alguém quer acessar o arquivo /index.html do site www.anselme.com.br ele faz a seguinte requisição

GET /index.html HTTP/1.1
Host: www.anselme.com.br

Porém quando estamos falando de APIs estamos colocando um contexto um pouco mais específico, indicando que os recursos podem ser mantidos de diferentes modos. Por exemplo, se houvesse um recurso chamado /clients/{id} seria possível opera-lo com os verbos GET, POST, PUT, PATCH ou DELETE. Ao fazer isso é possível obter, alterar (total ou parcialmente), criar, excluir.

DELETE /clients/10 HTTP/1.1 
Host: www.anselme.com.br

REST

Após entender a dinâmica das APIs HTTP surge uma primeira dúvida de buzz words: o que, raios, é REST? Vamos nos aprofundar um pouquinho nesse tema.

Roy Fielding foi uma dos responsáveis pela criação da web sugerindo, por exemplo, a criação do verbo PATCH para atualizações parciais. Embora a criação seja essencialmente creditada ao Sir Tim Berners-Lee , Roy teve uma participação relevante no projeto. Nesse período ele teorizou no seu doutorado um estilo arquitetural novo, inspirado em vários que ele observou nos idos de 2000 em Architectural Styles and the Design of Network-based Software Architectures.

Para Roy a internet possui uma estrutura de grafos onde uma página tem links dizendo o que pode ser acessado a partir dela. E ssim se ramifica indefinidamente. Para ele isso também deveria ser verdade para qualquer tipo de consulta e não apenas aquelas que retornavam páginas html. Então imagine um endpoint chamado /product/{ProductId} que recebe uma request do tipo GET. Imagine que o resultado dessa consulta além de entregar apenas dados do produto ele sugere acesso a links como /addToCart/{ProductId} ou /Order. E os novos endpoint dão acesso a outros endpoints.

GET /product/12345 HTTP/1.1
Host: www.anselme.com.br
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json

{
  "productId": "12345",
  "productName": "Tênis ABC de molas",
  "price": 229.99,
  "_links": {
    "addToCart": "/addToCart/12345",
    "Order": "/Order"
  }
}

Esse modelo sugere que há, na prática, um processo de negócio que indica as potenciais funções de algo, apontando para outros processos de negócio. Isso é um contraponto ao modelo SOAP onde um endpoint possui um Service que pode oferecer uma diversidade de resultados e formas sem a pretenção indicar o próximo passo do processo.

Hateoas

O HATEOAS (Hypermedia As The Engine Of Application State) ou Hipermedia Como Motor do Estado da Aplicação é um conceito fundamental do REST. Com ele você entende como Roy Fielding enxerga o design da web.

Para Roy a hipermídia é a rainha. Ela tem o papel de indicar que novas ações são possíveis com um determinado recurso. Para fazer uma analogia, sabe quando você liga para uma operadora de telefonia na intensão de cancelar sua linha telefônica? É quase mais ou menos assim:

  • Digite 1 para conhecer novos planos
  • Digite 2 para indicar que houve uma perda de disponibilidade
  • Digite 3 para cancelar a sua linha
  • Digite 4 para ouvir novamente
  • Digite 0 para voltar ao menu anterior

Ao escolher a opção 3 novas opções aparecerão. Esse é um modelo de navegação diferente do uso tradicional de APIs. Entenda que o próprio conceito de páginas HTML com links (tag A com href apontando para outros links) é a manifestação desse design, sob certo ponto de vista.

Design de máquina de estados

Esse design foi projetado para que seja possível interpretar os recursos como uma maquina de estados, possibilidando a navegação e atualização dos diferentes estados. Para exemplificar, vamos ver um cenário possível que se aplica. Vamos considerar uma franquiadora que tem diversas franquias com condições como: franquia fechada, franquia aberta, franquia em reforma, etc.

Essa estrutura poderia ser acessada através de alguns endpoints, como pode ver em exemplos a seguir:

  • GET /franquia
    • Obter o Estado Atual da Franquia
  • POST /franquia/abrir
    • Abrir uma Franquia
    • Inclui links para iniciar a construção, colocar em pausa, iniciar reforma e eliminar
  • POST /franquia/construcao
    • Iniciar Construção
    • Inclui links para obter o estado atual da construção.
  • PUT /franquia/construcao/concluir
    • Concluir Construção
    • Inclui links para retomar atividades, iniciar reforma e eliminar.
  • POST /franquia/pausa
    • Colocar em Pausa
    • Inclui links para retomar atividades, iniciar reforma e eliminar.
  • POST /franquia/retomar
    • Retomar Atividades
    • Inclui links para colocar em pausa, iniciar reforma e eliminar.
  • POST /franquia/reforma
    • Iniciar Reforma
    • Inclui links para obter o estado atual da reforma e concluir reforma.
  • PUT /franquia/reforma/concluir
    • Concluir Reforma
    • Inclui links para retomar atividades, colocar em pausa e eliminar.
  • DELETE /franquia/eliminar
    • Eliminar Franquia
    • Inclui links para obter o estado atual da eliminação.
  • GET /franquia/eliminacao
    • Obter Estado Atual da Eliminação

Formato de retorno

Utilizar HATEOAS implica em ter um certo padrão das requisições e respostas. Inicialmente tenha em mente que os recursos sempre são vistos como entes que possuem estados. Não considerar isso falha na largada. E na resposta (response HTTP) há sempre uma representação dos diferentes estados que esse recurso ou outros recursos podem assimir a partir dessa ação feita. Normalmente se utiliza um item chamada _links.

POST /franquia/abrir
Content-Type: application/json

{
  "nome": "Franquia ABC do João das Coves",
  "localizacao": "Rua João das Coves, 123456",
  "tipo": "Restaurante",
  "dataAbertura": "2023-11-01"
}

Note que a resposta HTTP 201 Created traz as informações do item criado, a rota self e o acesso aos demais estados. No caso in loco vemos apenas um recurso, mas podemos lidar com diferentes recursos a medida que um estado os torna acessível.

HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "123",
  "nome": "Nova Franquia",
  "localizacao": "Rua Principal, Cidade",
  "tipo": "Restaurante",
  "dataAbertura": "2023-11-01",
  "estado": "Aberta",
  "_links": {
    "self": {
      "href": "/franquia/123"
    },
    "construcao": {
      "href": "/franquia/123/construcao",
      "method": "POST"
    },
    "pausa": {
      "href": "/franquia/123/pausa",
      "method": "POST"
    },
    "reforma": {
      "href": "/franquia/123/reforma",
      "method": "POST"
    },
    "eliminar": {
      "href": "/franquia/123/eliminar",
      "method": "DELETE"
    }
  }
}

Transferência de estado

Esse é outro detalhe implícito na arquitetura REST que não pode ser esquecido. Se um por um lado a aplicação lida com recursos com estados e com potenciais ações que os atualiza, por outro lado há o estado propriamente dito, que é trafegado pelas diferentes camadas. Então, de certa maneira é correto considerar que o estado que estava no lado do servidor passou para a aplicação cliente que, no final de uma ação pode retornar para o servidor. Claro que essa é uma questão puramente teórica para deve ser sempre considerada nesse design.

Retornos de erro

Vale saber que quando falamos de erros na arquitetura baseada na transferência de estado, estamos pensando na RFC 7807 ou “Problem Details for HTTP APIs”. Ela traz uma modelo pré-estruturado para que essa comunicação seja mais eficaz. Vamos a um exemplo simples:

HTTP/1.1 404 Not Found
Date: Fri, 03 Nov 2023 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

{
   "name": "Not Found Exception",
   "message": "The requested resource was not found.",
   "code": 0,
   "status": 404
}

Melhor usar o SOAP?

Quem já trabalhou com o SOAP sabe como ele é. Assim, trata-se de uma outra abordagem web que considera que os endpoints são serviços e não estados e um recurso. Então, nesse modelo no desenvolvimento da aplicação cliente é possível fazer um discovery e saber quais são todos os métodos e possíveis estados de retorno utilizando XMLs sofisticados. No ambiente de desenvolvimento microsoft era relativamente fácil fazer isso pela experiência da IDE Visual Studio, mas isso não era realidade para todo o mercado.

Além disso o uso do SOAP se encaminhava para uma arquitetura chamada SOA (Service Oriented Architecture ou Arquitetura orientada a serviços) que repidamente se transformava num emaranhado complexo e de difícil gestão, em especial de suas versões. Esse modelo imperou no passado, mas hoje é considerado legado. Eu particularmente entendo sua relevância mas os modelos atuais de modo geral se parecem mais adequados.

Para concluir essa parte, devemos entender que o padrão REST vem como um contraponto da visão dos serviços web, mas sem a flexibilidade de um cliente saber de antemão os métodos e retornos possíveis.

Rest ou Restful

Na minha humilde visão, esses termos são apenas uma bobagem conceitual e de nomenclatura, explorados excessivamente pelo mercado. Assim, parte dessa exploração se dá por que há grande interesse em vender livros e cursos; e outra parte é por que não são muitos aqueles que se interessam em estudar efetivamente o tema.

Desse modo, para Roy Fielding o REST (Representational State Transfer) é um estilo arquitetural, definido em sua tese de doutorado. Assim, isso significa que estruturas escritas em COM/COM+ para comunicação entre drivers do sistema operacional poderiam ser REST. Isso não tem nenhuma relação direta com APIs.

Mas, por outro lado, o ambiente de APIs (em especial APIs baseadas em HTTP) acolhe relativamente bem o modelo, embora eu questione o fato do retorno _links não exigir um padrão e as URIs não terem verbos em sua assinatura.

Entendido o que é o REST então o que é o RESTFul? Simples. É a implantação prática da arquitetura REST. Somente isso. Ocorre que um sujeito chamado Leonardo Richardson interpretou REST de outra forma, considerando-o um serviço que pode se apresentar como maquina de estado. Desse modo ele descreve uma escala de maturidade para identificar se a API REST é RESTFul ou não.

Entenda que para Roy Fielding (o autor do conceito) isso não faz sentido. Para ele, ou é RESTFul ou não é. Para Richardson isso depende do cumprimento de alguns critérios.

Modelo de Maturidade de Richardson

Como comentei o RMM ou Modelo de Maturidade de Richardson considera uma escala de critérios para identificar se sua API HTTP é RESTFul e quanto. O modelo considere níveis do zero ao quatro.

Nível 0 – POX (Plain Old XML ou POJO)

No Nível 0, a API é caracterizada por seguir uma abordagem parecida com o Remote Procedure Call (RPC). Aqui, não há diferenciação de verbos HTTP; geralmente, todas as operações são realizadas via POST para um endpoint, com todas as informações detalhadas no corpo da requisição. Um exemplo comum é o uso de Web Services ASMX.

Nível 1 – Recursos

Ao avançar para o Nível 1, o foco passa a ser no conceito de recursos, representados por URLs. Nesse nível, a API identifica recursos, mas a nomenclatura dos verbos não é padronizada de acordo com os princípios REST. Por exemplo, ao tentar excluir um recurso, a chamada pode ser GET /excluirXpto?id=1.

Nível 2 – Verbos

No Nível 2, a API começa a respeitar os verbos HTTP apropriados para operações específicas nos recursos. Isso significa que os métodos GET, POST, PUT e DELETE são usados corretamente. No entanto, os nomes dos recursos ainda podem conter verbos, o que não está completamente alinhado com a proposta REST.

Nível 3 – Controles de Hipermedia

O mais alto nível de maturidade, o Nível 3, é caracterizado pelo uso efetivo de hypermedia controls, onde a API retorna “_links” e recursos de hipermedia nas respostas. Esses links permitem a descoberta e a navegação entre recursos de maneira dinâmica, tornando a interação com a API mais intuitiva e flexível.

Reflexão sobre o Modelo de Maturidade de Richardson

Martin Fowler, um dos proeminentes nomes no campo da arquitetura de software, afirmou que o RMM é uma estrutura útil e incremental. No entanto, ele sublinha que não se deve considerar o modelo de maturidade como o único conceito, embora seja um guia passo a passo. Fowler argumenta que REST, assim como muitos conceitos na área de TI, possui várias nuances, mas destaca que o conceito definido por Roy Fielding deve ser considerado o canônico, fundamentando-se nos princípios estabelecidos por ele.

Conclusão de API HTTP, REST ou RESTFul

Em síntese, o post revela não apenas uma metodologia técnica, mas uma visão filosófica sobre a construção de sistemas distribuídos. Os princípios fundamentais de transferência de estado, a linguagem universal do HTTP e a aplicação do conceito HATEOAS não apenas conectam sistemas, mas redefinem a própria essência da interconectividade digital. Além disso, o Modelo de Maturidade de Richardson oferece uma bússola, que embora questionável ela é didática, guiando as implementações.


Thiago Anselme
Thiago Anselme - Gerente de TI - Arquiteto de Soluções

Ele atua/atuou como Dev Full Stack C# .NET / Angular / Kubernetes e afins. Ele possui certificações Microsoft MCTS (6x), MCPD em Web, ITIL v3 e CKAD (Kubernetes) . Thiago é apaixonado por tecnologia, entusiasta de TI desde a infância bem como amante de aprendizado contínuo.