IGTI Blog

Desenvolvimento de APIs

Conceitos básicos para conhecermos antes de construirmos uma API REST.

REST (Representational State Transfer) é um estilo arquitetural, e dessa forma define um conjunto de restrições e contratos arquiteturais. Uma API que é aderente às restrições e contratos REST é considerada RESTful. É projetado para fazer ótimo uso do protocolo HTTP. Essa é uma grande vantagem do REST, uma vez que a infraestrutura para atender esse protocolo como servidores, caches e proxies, é largamente disponível. O sucesso da Web – baseada no HTTP – é uma prova da longevidade e escalabilidade de arquiteturas baseadas no HTTP.

REST usa exatamente essas características que funcionam tão bem na web, para aplicá-las também no desenvolvimento de APIs. Antes de entrar em detalhes sobre REST, vamos esclarecer alguns equívocos quanto a esse estilo arquitetural: REST não é um padrão; REST não é um protocolo; REST é um estilo arquitetural constituído de algumas características baseadas no protocolo HTTP.

Recurso

Assim como no HTTP, o conceito central do REST é o resource. Um resource é uma abstração de um modelo de dados, o qual pode ser construído hierarquicamente e pode conter sub resources. Cada resource (e os sub resources) pode ser identificado por sua URI (Uniform Resource Identifier) única. Um resource é uma estrutura de dados, que pode ser serializada para várias representações concretas, como JSON ou XML. Para criar, recuperar, alterar e remover, um número de diferentes métodos são definidos. Portanto, nem todos os resources suportam todos os métodos.

Resources são quase como objetos da programação orientada a objetos (POO). Essa comparação vai até no que se refere a presença de campos de dados e métodos que manipulam esses campos. Existe, portanto, uma diferença importante entre REST e POO: os métodos em REST são descritos como um conjunto de métodos HTTP (GET, PUT, POST, …), enquanto em POO os métodos podem ser arbitrários. Esse conjunto de métodos HTTP é a interface comum do resource (uniform resource interface). Por outro lado, os métodos HTTP especificam a interface comum, ou seja, nenhum outro método pode ser usado para manipular o resource. Nenhum outro método pode ser especificado nas requisições de API e no HTTP body, nem no path base e nem nos parâmetros.

O termo API não é oficialmente definido em REST. Especificamos uma API como um resource-raíz, o qual pode conter outros sub resources. Qual a diferença entre APIs e resources? Resources formam modelos de dados hierárquicos. Nessa hierarquia, o resource raíz é de alguma forma especial. Ele é chamado de API. Uma API pode conter vários sub resources, que são tipicamente usados juntos.

Representação

Dados concretos são servidos na forma de representações. Pode-se pensar na representação como um resource serializado. Diferentes estruturas de codificação (ou tipos de mídia) podem ser usados para serialização. Dessa forma, cada resource pode ser apresentado em um número de representações. Qual a diferença entre resources e representações? Resources são uma abstração do modelo de dados. Assim que o resource é retornado para o cliente, é necessário que seja serializado numa representação concreta. As regras para criação dessas representações podem ser diferentes, produzindo XML ou JSON, mas todas representações de um mesmo resource contém a mesma informação: a informação do resource.

Interface Comum (Uniform Resource Interface)

REST APIs geralmente executam operações CRUD (create, read, update, delete), que podem ser facilmente mapeadas em métodos HTTPs: criação pode ser desempenhado pelo POST, leitura pode ser desempenhado pelo GET, alteração pelo PUT e a exclusão pelo DELETE. Esses métodos HTTPs constituem a interface comum (Uniform Resource Interface). Eles são os mesmos para todos os resources.

Cada método HTTP tem uma proposta específica e também define um conjunto de características: os métodos HTTPs podem ser seguros e idempotente. Métodos idempotentes podem ser executados repetidamente sem alterar o resultado final; executando o método múltiplas vezes tem-se o mesmo efeito, mesmo se fosse executado apenas uma vez. Métodos seguros não têm efeitos colaterais, não mudam o estado de um resource e são read-only.

Em REST, constrói-se resource orientado a interface. Com resource orientado a interfaces, estruturas de dados são abstrações, e um resource é uma interface. Um pequeno conjunto fixo de operações (métodos HTTPs) são usados para operar sobre a interface do resource. Um exemplo: se você quer um modelo de carrinho de compras de um e-commerce, você modelaria apenas o resource shoppingcar, o qual define a interface. O resource é construído sem a necessidade de especificar o uso dos métodos HTTPs do uniform resource interface.

REST é incompatível com os estilos baseados em procedimentos como SOAP e RPC. Quando definimos procedimentos orientados a interfaces, atividades ou operações são abstrações. Voltando ao exemplo do e-commerce e o carrinho de compra, poderíamos modelar usando SOAP ou RPC: createShoppingCar(), updateShoppingCar(id, newItem), getShoppingCart(id) e deleteShoppingCart(id).

REST define um conjunto de restrições para o projeto de API. A maioria das restrições são, na verdade, restrições HTTPs, e REST leva essas restrições para as APIs. O estilo REST assegura que APIs usem o HTTP corretamente. Essas restrições limitam a liberdade de projeto, então nem todo projeto é permitido. Usando o HTTP corretamente em APIs, você consegue propriedades desejadas. REST impõe as seguintes:

  •        Uso das capacidades HTTP ao máximo possível.
  •        Desenho dos resources (substantivos), não métodos e operações (verbos).
  •        Uso do uniform interface definido pelos métodos HTTPs, que  têm uma semântica bem definida.
  •        Comunicação stateless entre cliente e servidor.
  •        Uso de baixo acoplamento e independência dos requests.
  •        Uso dos códigos de HTTPs de retorno.
  •        Uso de media-types.

Estado

Em sistemas distribuídos, a informação precisa ser preservada entre as chamadas. A preservação dessa informação é camada de “estado”. Uma vez que os sistemas distribuídos consistem de dois componentes: cliente e servidor, o estado pode ser preservado em qualquer um dos componentes. Um componente, que armazena a informação de estado entre as chamadas, é chamado de stateful. Um componente que é agnóstico quanto ao estado da informação é chamado de stateless.

De acordo com a conhecida restrição do REST, os componentes servidores são stateless e toda a informação é armazenada em clientes stateful. Componentes do lado servidor são stateless no sentido de que eles não armazenam informação de sessão entre as chamadas. Mas, isso é um pouco mais complicado. Isso causa muita confusão sobre o tópico de manutenção do estado no REST. Vamos a um exemplo: Se um cliente armazena um objeto no servidor, o estado do servidor não muda? Ainda é RESTful mesmo se referindo ao estado dos componentes no lado do servidor? A confusão se ameniza, quando percebemos que existe, na verdade, dois tipos de estado numa aplicação RESTful: estado da aplicação e o estado do resource.

O estado da aplicação é usado para manter o rastreamento das interações numa única instância de uma aplicação cliente. Estado da aplicação não é compartilhado com as aplicações clientes, é dedicado com uma instância de aplicação única. Em muitos sistemas não-REST, o estado da aplicação é assegurado por um objeto de sessão no servidor. O objeto de sessão é criado ou alterado como um efeito colateral da chamada do cliente a uma funcionalidade no lado do servidor.

Em sistemas REST, portanto, o estado da aplicação é armazenado apenas no lado cliente – não do lado do servidor e dessa forma não na API. As APIs não mantém o estado da aplicação. Cada requisição da API deve ser independente das requisições anteriores. Esse é o motivo no qual todo request deve conter toda a informação necessária. Esse princípio do modelo stateless assegura que a infraestrutura pode ser escalável facilmente e dinamicamente (e o estado da aplicação não importará no momento da escalabilidade). Uma vez que o estado da aplicação é gerenciado pela aplicação cliente, a API consumidora necessita cuidar dessa característica e é de responsabilidade da API consumidora construir clientes de acordo com esse padrão.

O estado de resource representa o estado dos objetos de negócio, o qual se torna disponível como um resource REST. Ele é compartilhado por toda a aplicação e todas instâncias. Para compartilhar a informação, a única opção viável é o armazenamento do estado do resource no servidor. É de responsabilidade da API fornecer mecanismos para mudar o estado do resource. Os métodos HTTPs POST, PUT, PATCH e DELETE são tipicamente usados para alterar o estado do resource via API.

Conclusão

O REST é baseado no HTTP, o que lhe permite o uso de todas as vantagens do HTTP, bem como as desvantagens. Os principais elementos desse estilo arquitetural é o resource, representação, interface comum, e estado. Esse estilo se baseia também na comunicação stateless fazendo com que a informação de estado fique do lado do cliente e em relação à preservação da informação da comunicação (estado), temos o estado da aplicação e o estado do resource. O estado da aplicação é usado para manter o rastreamento das interações numa única instância de uma aplicação cliente, ou seja, um cliente não conhece o estado do outro, não compartilha. Já o estado do resource representa o estado dos objetos do negócio sendo compartilhado e acessado por vários clientes.

Professor autor: Cristiano Santos Botelho