Arquitetura

Saiba como usar REST patterns corretamente

REST patterns (Representational State Transfer) é um conjunto de princípios de arquitetura para API (Application Programming Interface), utilizado hoje no mundo como principal forma de integração entre sistemas. Mesmo esses princípios estando no mercado há um bom tempo, muitos desenvolvedores ainda pecam esquecendo das boas práticas na hora de criar API’s. Para ajudar nesse ponto, trazemos alguns dos principais padrões de design para desenvolvimento de API REST.  

Métodos HTTP e Status code

API’s REST  muitas vezes são confundidos com HTTP por andarem lado a lado. Porém, REST não necessariamente precisa utilizar o protocolo de comunicação HTTP. É possível utilizar outros protocolos de comunicação menos populares – como FTP e SMTP – e ainda assim sua API pode ser REST. 

Como a maioria das API’s REST são desenvolvidas em cima do protocolo HTTP, faz sentido criarmos API’s em cima dos métodos HTTP já bem definidos, também chamados de verbos HTTP. 

  • GET: Buscar recursos
  • POST: Criar um novo recurso
  • PUT: Atualizar um recurso existente
  • DELETE: Remove um recurso existente
  • PATCH: Atualizar parte de um recurso existente

Um anti-pattern muito comum encontrado nas API’s é a utilização do verbo POST para edição e deleção, quando a boa prática seria utilizar o PUT para edição e DELETE para deleção. Esses métodos disponibilizam um status code de retorno, que ajudam a descrever a mensagem de retorno da API. Abaixo segue alguns dos principais status codes utilizados no dia a dia.

  • 200 Ok: Consulta concluída com sucesso.
  • 201 Created: A operação resulta na criação de um novo recurso.
  • 204 No content: Request com sucesso, porém sem nada a retornar.
  • 400: Bad request: A requisição foi mal formada, omitindo atributos obrigatórios, seja no payload ou através de atributos na URL.
  • 401: Unauthorized: Cabeçalho de autenticação ausente/inválido ou token inválido.
  • 403: Forbidden: O token tem escopo incorreto ou uma política de segurança foi violada.
  • 404: Not found: O recurso solicitado não existe ou não foi implementado.
  • 405: Method Not Allowed: O consumidor tentou acessar o recurso com um método não suportado.
  • 429: Too Many Requests: A operação foi recusada, pois muitas solicitações foram feitas dentro de um determinado período ou o limite global de requisições concorrentes foi atingido.
  • 500: Internal Server error: Ocorreu um erro no gateway da API ou no microsserviço.
  • 503: Service unavailable: O serviço está indisponível no momento.
  • 504: Gateway Timeout: O servidor não pôde responder em tempo hábil.

Nomenclatura de endpoints

No REST, a representação dos dados é chamada de recurso. Ter uma estratégia consistente de nomenclatura é muito importante no longo termo. Qualquer informação pode ser nomeada como um recurso: imagens, documentos, uma coleção de outros recursos, e assim por diante.

Um recurso pode ser um objeto único ou então uma coleção de dados. Por exemplo, ‘clientes’ é uma coleção e ‘cliente’ é um recurso único, caso estivéssemos desenvolvendo uma API para um banco. Podemos identificar o recurso com uma coleção de clientes através da seguinte URI “/clientes”, e para um único cliente em específico utilizando a URI “/clientes/{clienteId}”.

Um recurso pode conter sub coleções de recursos também. Ainda utilizando a ideia de uma API para um banco, podemos usar o seguinte exemplo. Uma subcoleção de ‘contas’ de um ‘cliente’ em particular pode ser identificado da seguinte forma “/clientes/{clienteId}/contas”. E da mesma forma uma conta em específica pode ser identificada como “/clientes/{clienteId}/contas/{contaId}”.

A REST API desenvolvida de uma forma com que a URI aponte os recursos que fique intuitiva e clara,  facilita muito o consumo pelos desenvolvedores cliente, fazendo com que ele não perca tempo correndo atrás de quem sabe explicar o que aquela API está fazendo.

Exemplos do dia a dia:

Imaginando que temos uma API de gestão de chamados de suporte, poderíamos utilizar alguns endpoints da seguinte maneira:

  • GET /tickets/12/messages – busca uma lista de messages para ticket #12
  • GET /tickets/12/messages/5 – Busca uma message #5 para ticket #12
  • POST /tickets/12/messages – Cria uma nova mensagem para o ticket #12
  • PUT /tickets/12/messages/5 – Atualiza uma message #5 para ticket #12
  • PATCH /tickets/12/messages/5 – Atualiza parcialmente uma message #5 para ticket #12
  • DELETE /tickets/12/messages/5 – Deleta message #5 para ticket #12

Dicas para definir melhor sua API:

A URI deve declarar o recurso sempre com um adjetivo (a não ser alguns casos específicos que falarei mais adiante) ao invés de usar um verbo representando uma ação, porque adjetivos têm propriedades que o verbo não tem. Por exemplo:

  • Usuários do sistema
  • Contas do usuário
  • Dispositivos de rede e etc…

E suas URI’s de poderiam ser modeladas da seguinte forma sem a utilização de verbo:

http://api.exemplo.com.br/gestao-dispositivos/distpositivos

http://api.exemplo.com.br/gestao-dispositivos/distpositivos/{dispositivoId}

http://api.exemplo.com.br/gestao-usuarios/usuarios

http://api.exemplo.com.br/gestao-usuarios/usuarios/{usuarioId}

O caso onde utilizamos verbos na nomenclatura é quando o recurso é tratado como como se fosse um executável. Exemplo:

http://api.exemplo.com.br/gestao-musicas/usuarios/{usuarioId}/playlist/play

Na sequência segue algumas outras dicas para manter seus recursos de acordo o padrão:

  • Letras minúsculas devem ter prioridade para evitar problemas, pois a URI é case sensitive.
  • A URI não deve ser utilizada para indicar uma ação de CRUD, para isso temos os verbos HTTP para nos ajudar a identificar o tipo de ação.

Filtros e paginação

Muitas vezes vamos passar por situações onde precisamos criar API’s que retornem uma coleção de recursos, porém não somente entregar essa coleção, mas sim ter a opção de poder filtrar, ordenar e paginar. Para isso devemos usar os query parameters, assim como nos exemplos a seguir:

http://api.exemplo.com.br/gestao-dispositivos/dispositivos-gerenciado

http://api.exemplo.com.br/gestao-dispositivos/dispositivos-gerenciado?regiao=BR

http://api.exemplo.com.br/gestao-dispositivos/dispositivos-gerenciado?regiao=BR&marca=XYZ

http://api.exemplo.com.br/gestao-dispositivos/dispositivos-gerenciado?regiao=BR&marca=XYZ&sort=data-instalacao

Versionamento

Mudanças em API são inevitáveis devido a mudança frequente de requisitos de negócio. Cada requisito modificado ou novo pode trazer mudanças significativas nos recursos das API ‘s. É muito importante proteger os clientes existentes, pois uma mudança na API pode gerar problemas de quebra de contrato para quem já consome e assim ocasionando em erros no sistema. Outro ponto é que devemos nos manter flexíveis o suficiente para atender novas mudanças de requisitos e expor esses novos recursos. Para solucionar esses pontos, é possível utilizar um versionamento de API.

Uma forma bem comum de versionamento é através da URL do recurso, colocando o número da versão na URI. Com isso temos a vantagem que enquanto as URI’s já existentes vão continuar funcionando como previamente definido no contrato, a nova API com uma nova versão na URI pode entregar um processo diferente do que estabelecido na versão anterior contendo os novos requisitos de sistema. Abaixo segue duas imagens mostrando como ficaria uma API com mudança de versão.

(API 1.0)

(API 2.0

Conclusão

É importante sempre parar para analisar se o que está sendo construído está de acordo com as boas práticas de desenvolvimento REST, reforçando o ponto de que a API deve estar bem clara, de forma com que o cliente compreenda o que está sendo feito quando utilizar a API. Depois de que o código esteja em produção e sendo consumido fica muito mais complicado alterar, pois vai gerar uma quebra de contrato, sendo assim só gerando uma versão nova. Esperamos que esse post possa ajudar você a entregar uma API clara utilizando boas práticas de desenvolvimento.

Referência

%d blogueiros gostam disto: