xphub / forum

Hub de inovações e experiências relacionadas à Web
Creative Commons Zero v1.0 Universal
4 stars 0 forks source link

Experiência de quem consome: Padronize sua API! #1

Open danielbonifacio opened 5 years ago

danielbonifacio commented 5 years ago

REST

Um guia de padronização para requisições em APIs REST maduras.

Alguns termos utilizados nesse guia foram criados por mim (filtros de escopo, etc.) Talvez você tenha uma melhor nomenclatura. Defina como achar mais fácil de explicar.

Paradigmas

Para facilitar, tanto a criação, quanto o consumo de APIs, é importante entender o paradígma em que ela se baseia. A proposta deste guia orientar como (e por qual motivo) desenvolver APIs padronizadas.

Verbos

Directory based

A forma mais habitual de buscar por algo, seja qual for sua finalidade (deletar, criar um novo, atualizar, etc.) já está instaurada dentro dos sistemas operacionais, que é a busca por diretórios. É uma forma simples, e, se analisarmos, podemos aplicar isso em nossa API para torná-la mais fácil de ser consumida.

Requisitando todos os produtos:

method: GET
content-type: application/json
url: https://minhaapi.com/produtos
[
  {
    "_id": 1,
    "_prepend": "camisas",
    "nome": "Camisa Masculina Estampa Queen",
    "preco": 89.90,
    "moeda": "R$",
  },
  {
    "_id": 2,
    "_prepend": "camisas",
    "nome": "Camisa Feminina Estampa Queen",
    "preco": 79.90,
    "moeda": "R$",
  }
]

Atualizando dados de uma camisa:

method: PUT
content-type: application/json
url: https://minhaapi.com/produtos/camisas/2
data: {
  "tamanhos": ["M", "G", "GG", "G3"]
}
{
  "_id": 2,
  "_prepend": "camisas",
  "nome": "Camisa Feminina Estampa Queen",
  "preco": 79.90,
  "moeda": "R$",
  "tamanhos": ["M", "G", "GG", "G3"],
}

Filtros

Filtros podem fazer parte do slug de uma requisição ou não. Isso vai variar de caso para caso.

Filtros globais

Vamos usar o exemplo das camisas acima. Reparem que, antes do id da camisa, na segunda requisição, houve um prepend de "camisa", e isso é um filtro global.

Filtros globais são filtros majoritários, eles controlam estados mais comuns de requisições, e servem para dar um "norte" ao consumidor ou fazer parte da hierarquia de estrutura. URL amigável não é útil somente para o usuário final.

Porém, filtros globais em APIs sofrem com o mesmo problema de variáveis globais dentro do da programação: fácil conflito.

Filtros de escopo

Vamos dizer que eu quero pegar o produto com "_id": 3 da minha lista de produtos. Eu iria consumir algo assim: GET -> https://minhaapi.com/produtos/3 certo?

E se eu quisesse, agora, listar os itens da terceira página? Qual seria o endpoint? Filtros de escopo podem resolver e simplificar ainda mais sua API.

Filtros de escopo são, basicamente, parâmetros na URL:

GET -> https://minhaapi.com/produtos?pagina=3

Uma das vantagens de usar filtros de escopo, é que eles podem ser múltiplos:

GET -> https://minhaapi.com/produtos?categorias=camisas&menor=M&maior=G

Isso deixa sua API mais flexível e isso é ótimo até certo ponto.

Respostas

No exemplo de atualização do produto acima, note que em uma requisição de atualização nos retornou um registro. E está tudo bem com isso.

Quando atualizamos, inserimos ou (semanticamente) deletamos registros, alguns metadados podem ser atualizados também, como, por exemplo, uma propriedade lastUpdate, isActive ou createdAt dentro do objeto em questão, e esses dados podem ser necessários (ou ajudar) quem consome a API.

Uma aplicação mobile, por exemplo, ao cadastrar um novo item, não irá precisar reenviar uma requisição para o servidor trazendo todos os dados que ele já tinha localmente para atualizar seu repositório com um novo item apenas.

Também evite o uso de chaves para objetos de resposta como "data", "res" ou mesmo o nome do que está sendo requisitado.

Se quem consome buscou por produtos, a resposta pode ser:

[
  { "nome": "camisa.... }
]

e não:

"produtos": [
  { "nome": "camisa.... }
]

CORS

CORS é um padrão de segurança que os navegadores modernos seguem, e seus prefilghts podem fazer da vida do consumidor um verdadeiro inferno. Prepare sua API para receber esse tipo de requisição, caso seu (ou parte dele) consumidor depender de um navegador.

Migração e evolução

É comum haver evolução em nossas APIs com o tempo, e existem endpoints que se tornam obsoletos. Se não houver motivos estritos para remover um endpoint por completo, deixe ele lá, acessível. Adicione um header warning com as instruções detalhadas de como efetuar a troca.

Estes são pontos chaves que eu como desenvolvedor acho importantes na hora criar APIs, pois nosso usuário, quando se trata de APIs, é o próprio desenvolvedor (sua equipe, a comunidade, ou até mesmo você!) e podemos facilitar a vida de todos.

Lembrando que, mesmo seguindo todos estes padrões, é bom documentar sua API e adaptar à sua realidade. Não precisa criar 20 filtros de escopo diferentes, sendo que você não vai usar. Deixe para criar depois, caso necessário.

danielbonifacio commented 5 years ago

Também é interessante ressaltar a possibilidade e importância de APIs gateway. Um resumão poderia ser: APIs gateway são um ponto único de entrada do cliente, sendo esta responsável por se conectar aos microsserviços e/ou outras APIs.

Alguns links: