Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Informações
titleRestrições para uma API RESTful

RESTful seria, então, a API que está de acordo com todas as restrições definidas por Roy.

Os principais critérios para uma API ser RESTful são:

  • Uniform Interface;
    • Resource-based: tenta lidar com recursos invés de métodos;
    • Manipulation of resources through representations: recursos através de uma representação (JSON, XML, HTML.);
    • Self-descriptive Messages:  As respostas são auto descritivas, incluindo informação suficiente para que o cliente saiba como utilizá-las;
    • HATEOAS: Padrão que sempre inclui links uteis junto as respostas de uma requisição.
  • Stateless;
    • Não guarde nenhum tipo de estado referente a comunicação;
  • Cacheable;
    • Reduzir o número de chamadas feitas para o endpoint e também melhorar a latência de solicitações para a sua API.
  • Client-Server;
    • web/aplicação deve ser separada da solicitação/armazenamento dos dados.
  • Layered system.
    • O cliente nunca deve chamar diretamente o servidor da aplicação sem antes passar por um intermediador, no caso, pode ser um load balancer ou qualquer outra máquina que faça a interface com o(s) servidor(es)

Sem seguir todas estas restrições, sua API não será RESTful, será apenas mais uma implementação RPC em cima do protocolo HTTP.

Deck of Cards
idPadrões
Card
labelURIs legíveis - Endpoints

Padrão de nomenclatura 

http://{{host}}/api/{{agrupador}}/{{versão}}/{{resource}}

  • Dê preferência para o plural ao disponibilizar o resource. Utilize /users ao invés de /user;
  • Dê preferência para URL's em minúsculo, evite GET /Users, use GET /users;
  • Na API, utilizamos semantic versioning, um padrão que é dividido em major, minor e patch. Somente a Major Version é utilizada na URL. Por exemplo: V1 ou V2; 
  • Deve ser orientada a recursos representados por substantivos no plural. Não se deve orientar a verbos Get, Put, Post e Delete.

A raiz do resource deve retornar uma coleção. Por exemplo /users deve retornar um lista de usuários.
Se desejar obter um resource especifico utilize o nível seguinte especificando seu identificador único. GET /users/2. Não precisa ser o id do banco, poderia ser outro campo, desde que seja identificador único. Um usuário poderia ser o username.

  • GET /users -> Retorna uma lista de usuários
  • GET /users/bruno -> Retorna o usuário com username bruno
  • POST /users -> Cria um usuário
  • PUT /users/bruno -> Atualiza o usuário bruno
  • PATCH /users/bruno -> Atualiza parcialmente o usuário bruno
  • DELETE /users/bruno -> Remove o usuário bruno

Relacionamento filho - Se existir alguma tabela filho do resource, eles devem estar mapeados para o mesmo endpoint. Exemplo

  • GET /users/bruno/claims -> Retorna uma lista de claims do usuário bruno
  • GET /users/bruno/claims/6 -> Retorna o claims com Id 6
  • POST /users/bruno/claims -> Cria uma claim para usuário bruno
  • PUT /users/bruno/claims/6 -> Atualiza a claim 6 do usuário bruno
  • PATCH /users/bruno/claims/6 -> Atualiza parcialmente a claim 6 do usuário bruno
  • DELETE /users/bruno/claims/6 -> Remove a claim 6 do usuário bruno

Chave composta

  • GET /sales/20_1020/rules -> Retorna uma lista de regras da coligada 20 e venda 1020
  • GET /sales/20_1020/rules/6 -> Retorna uma a regra 6 da coligada 20 e venda 1020
  • POST /sales/20_1020/rules -> Cria a regra 6  da coligada 20 e venda 1020
  • PUT /sales/20_1020/rules/6 -> Atualiza a regra 6  da coligada 20 e venda 1020
  • PATCH /sales/20_1020/rules/6 -> Atualiza parcialmente a regra 6  da coligada 20 e venda 1020
  • DELETE /sales/20_1020/rules/6 -> Remove a regra 6  da coligada 20 e venda 1020

Exemplo 

[RoutePrefix("imb/v1/modalities")]  

[Route("{modalityId}/enterprises/{companyId}_{enterpriseId}")]
[HttpGet]
public List<ImbVendaModalidadeRegraEntity> GetTabelaPrecoModalidade(int modalityId, int companyId, int enterpriseId)


As propriedades devem ser sempre em minúsculo 

[JsonProperty("codcoligada")]


Evite adicionar na URI a operação a ser realizada no recurso

Os recursos que uma aplicação gerencia podem ser manipulados de diversas maneiras, sendo para isso disponibilizada algumas operações para manipula-los, tais como: criar, listar, excluir, atualizar, etc.

A manipulação dos recursos deve ser feita utilizando-se os métodos do protocolo HTTP, que inclusive é um dos princípios do REST que será discutido mais adiante.

Portanto, evite definir URIs que contenham a operação a ser realizada em um recurso, tais como:

  • GET/PUT/DELETE/PATCH /users/Cadastrar;
  • GET/PUT/DELETE/PATCH /users/bruno/Excluir;
  • GET/PUT/DELETE/PATCH /users/bruno/Atualizar.


Logo ações se fazem necessários no dia-a-dia. E é importante reforçar que não fere os padrões REST.

  • POST /candidatos/{id}/candidatar -- Grava a aplicação de um candidato a uma vaga
  • POST /candidatos/{id}/aprovar -- Aprova um candidato
  • DELETE /candidatos/{id}/aprovar -- Cancela a aprovação
  • POST /candidatos/{id}/reprovar -- Reprova o candidato
  • DELETE /candidatos/{id}/reprovar -- Cancela a reprovação
  • POST /candidatos/{id}/transferir -- Transfere o candidato para outra vaga
  • DELETE /candidatos/{id}/transferir -- Cancela a transferência

Nesse formato a comunicação é clara. No backend o desenvolvedor não vai precisar criar if's ou switchs e traduzir a intenção do método "CRUD". O próprio endpoint comunica sua intenção.

Card
labelVerbos HTTP

Os recursos gerenciados por uma aplicação, e identificados unicamente por meio de sua URI, geralmente podem ser manipulados de diversas maneiras. É possível criá-los, atualizá-los, excluí-los, dentre outras operações.

Quando um cliente dispara uma requisição HTTP para um serviço, além da URI que identifica quais recursos ele pretende manipular, é necessário que ele também informe o tipo de manipulação que deseja realizar no recurso. É justamente aí que entra um outro conceito da Web, que são os métodos do protocolo HTTP.

O protocolo HTTP possui diversos métodos, sendo que cada um possui uma semântica distinta, e devem ser utilizados para indicar o tipo de manipulação a ser realizada em um determinado recurso.

Vejamos agora os principais métodos do protocolo HTTP e o cenário de utilização de cada um deles:

  • GET: Obter os dados de um recurso.

  • POST: Criar um novo recurso.

  • PUT: Substituir os dados de um determinado recurso.

  • PATCH: Atualizar parcialmente um determinado recurso.

  • DELETE: Excluir um determinado recurso.

  • HEAD: Similar ao GET, mas utilizado apenas para se obter os cabeçalhos de resposta, sem os dados em si.

  • OPTIONS: Obter quais manipulações podem ser realizadas em um determinado recurso.

Geralmente as aplicações apenas utilizam os métodos GET, POST, PUT e DELETE, mas se fizer sentido em sua aplicação utilizar algum dos outros métodos, não há nenhum problema nisso.


HTTP MethodIdempotenteSafe
OPTIONS
  •   
  •   
GET
  •    
  •   
HEAD
  •    
  •   
PUT
  •     
  •   
POST
  •    
  •   
DELETE
  •    
  •   
PATCH
  •    
  •   


Idempotente significa que o endpoint pode ser chamado várias vezes sem resultados diferentes. Não importa se o método é chamado apenas uma ou dez vezes. O resultado deve sempre o mesmo. Isso se aplica apenas ao resultado, não ao próprio recurso.

Safe são métodos Read-only. Isso significa que são seguros e não importa quantas vezes chamar, ele não irá alterar o estado do resource.


Card
labelRespostas

Quando o servidor recebe uma solicitação HTTP, o cliente deve saber o resultado da ação. Se houve sucesso ou falhou. Os códigos de status HTTP são vários códigos padronizados, com várias explicações em vários cenários. O servidor sempre deve retornar o código de status correto.

A seguir estão as categorias dos códigos HTTP:

  • 2xx - Status de sucesso
  • 3xx - Categoria de redirecionamento
  • 4xx - Erro no Cliente
  • 5xx - Erro no server

2xx - Sucesso

Abaixo uma tabela de quando utilizar cada um dos Status Code.

  • 200 Ok - Padrão que representa sucesso. Resposta padrão para GET, quando há resultados.
  • 201 Created - Indica que um recurso foi criado. Utilize para a resposta do POST. E também retorne o Header Location indicando o GET dessa informação.
  • 204 No Content - Representa que a request foi processada com sucesso, mas não há conteúdo para ser retornado. Utilize para PUT, PATCH e DELETE. E também para situações em que o GET não retornou resultados.
  • 202 Accepted - Indica que o servidor aceitou a request. Esse é um ótimo Status para processos assíncronos. Por exemplo um cenário onde o usuário faz upload de uma planilha que será processada em background.

3xx - Redirect

Como desenvolvedor, não consigo visualizar cenários em que será utilizado o redirect a partir de uma API RESTFul.

Em geral o 302 é bastante utilizado em desenvolvimento Frontend, como Razor. E o 301 Moved Permanently é utilizado por sysadmins, para indicar que um site foi permanentemente redirecionado para um novo endereço.

4xx - Client error

Indica que o client cometeu uma falha na requisição.

  • 400 Bad Request - A solicitação não foi processada, pois o servidor não entendeu o que o cliente está solicitando.
  • 401 Unauthorized - Indica que o client não está autenticado e não tem autorização para acessar o recurso.
  • 403 Forbidden - Indica que o Client está autenticado e a requisição é válida. Porém o client não tem permissão de acesso naquele recurso.
  • 404 Not Found - indica que o recurso não foi localizado.
  • 422 - Unprocessable Entity - A validação não pode ser processada por que algum valor inválido foi enviado na requisição. 

5xx - Erros no servidor

Os status 5xx há dois que merecem destaque. É o erro 500, houve uma falha no servidor e não conseguiu processar a requisição. E o erro 503 que vai botar o pessoal de infra para correr. Indica que o serviço está indisponível. Status comum quando o Webserver sobrecarrega de requisições e não consegue mais processar nenhuma requisição. O 503 é comum em cenários de ataques DDoS.


Image Added

Card
labelDocumentação

O Open Api, anteriormente conhecido como Swagger, é hoje o padrão mais utilizado para documentar API's. No ASP.NET Core é muito fácil configurar. Ele disponibiliza mecanismos para testar sua API no Browser.

swagger-1Image Added

Card
Endpoints
labelImplementado APIs TCGI

Incluir Página
Implementando APIs TCGI
Implementando APIs TCGI


Card
labelEndpointsApi de DataServer

Exemplos de uso de api de dataserver


Verbo: Get

Ação: Com filtro

URI: http://localhost:8051/rmsrestdataserver/rest/ImbPVIClienteData?filter= ["nome like :nome and CPFCNPJ = :cpf", "%teste%", "044.266.846-50"]


Verbo: Get

Ação: Primary Key

URI: http://localhost:8051/rmsrestdataserver/rest/ImbPVIClienteData/2


Verbo: Get

Ação: Primary Key Composta

URI: http://localhost:8051/rmsrestdataserver/rest/FinCFODataBR/1$_$C100338


Verbo: POST

Ação: Somente para inserir

URI: http://localhost:8051/rmsrestdataserver/rest/ImbPVIClienteData

[

    {        

        "ID":-1,

         "NOME": "teste api 5",

         "CPFCNPJ": "044.266.846-50",

         "TIPO": 0,

         "TIPOPESSOA": 0,

         "DATAHORACADASTRO":"2022-10-27T11:09:58.52-03:00",

         "INSCRICAOESTADUAL":" ",

         "CONJUGE_PROFISSAO_ID": 1,

         "LEAD": 0,

         "LEAD_POTENCIAL": 0        

    }

]


Verbo: DELETE

Ação: Deletar o registro com a primary key

URI:

http://localhost:8051/rmsrestdataserver/rest/ImbPVIClienteData/2



Verbo: PUT

Ação: Atualiza todos os registros, a lib faz o merge de todos os campos

URI:

http://localhost:8051/rmsrestdataserver/rest/ImbPVIClienteData/2


{

         "ID": 2,

         "NOME": "teste api PUT",

         "CPFCNPJ": "044.266.846-50",

         "TIPO": 0,

         "TIPOPESSOA": 0,

         "DATAHORACADASTRO":"2022-10-27T11:09:58.52-03:00",

         "INSCRICAOESTADUAL":" ",

         "CONJUGE_PROFISSAO_ID": 1,

         "LEAD": 0,

         "LEAD_POTENCIAL": 0        

    }


Verbo: PATCH

Ação: Atualiza alguns campos dos registros, a lib faz o merge somente dos campos enviados

URI:

http://localhost:8051/rmsrestdataserver/rest/ImbPVIClienteData/2

 

    {         

         "NOME": "teste api patch"                 

    }

 


Demais exemplos segue a documentação da lib: Serviços RESTful de DataServer no RM


Autenticação

Garantir a segurança dos dados também faz parte do desing de uma API, hoje o principal modelo utilizado pela comunidade é o Oauth 2.0, este é um padrão de autenticação, que foi construído para preservar os dados sensíveis de um usuário, minha recomendação seria sempre que possível utiliza-lo, porem caso não seja possível, não deixe sua API sem autenticação, no mínimo utilize uma autenticação do tipo basic, onde geralmente é criado um token em base64 a partir de um usuário e senha.

A utilização de Tokens de acesso, que são gerados pelo serviço REST  devem ser armazenados pelos clientes, via cookies ou HTML 5 Web Storage, devendo também ser enviados pelos clientes a cada nova requisição ao serviço.

Outras tecnologias e padrões para se trabalhar com Tokens:

  • OAUTH;
  • JWT (JSON Web Token);
  • Keycloack.

Stateless

Garanta que sua API não guarde nenhum tipo de estado referente a comunicação, toda requisição deve ser inteligente o suficiente para se resolver, sem armazenar quaisquer dados de seção.

Negociação de conteúdo

Apesar do ideal ser trafegar apenas JSON, caso sua API trafegue outros tipos de dados, por exemplo XML, utilize as chaves Accept e Content-Type do protocolo HTTP para detalhar todas as possibilidades

Paginação

Em requisições GET que retornem listas, devolva somente o necessário, pagine sua requisição, desta forma todos ganham, pois será trafegado somente o necessário, melhorando a experiência do usuário final.

Ordenação

Otimize suas requisições, facilite ainda mais a vida de seus clientes, permita que sua Api, ordene sua resposta, desta forma o cliente pode não precisar realizar nenhum tipo de tratamento no dado.

Respostas Parciais

Otimize ainda mais suas requisições GET, permita seus clientes recuperarem somente os campos que realmente necessitam, desta forma de ponta a ponta serão trafegado apenas os dados necessários.

Hateoas

Hateoas representa o termo Hypermedia as the engine of application State (Hipermídia como o mecanismo do estado do aplicativo), é um padrão que sempre inclui links uteis junto as respostas de uma requisição

Os principais benefícios de seguir essa abordagem são:

  1. As aplicações clients conhecem facilmente o limite e próximos passos de cada domínio
  2. As aplicações clients podem recuperar seus paths dinamicamente sem a necessidade de colocar-los fixo no código
  3. Os desenvolvedores da API podem alterar o esquema de paths sem quebrar as aplicações clients

<acao><rel>self</rel><uri>http://servicorest.com.br/pedidos/1459</uri><method>GET</method></acao>

Open Documentation

Alem de seguir as melhores práticas, faça ainda mais que isso, utilize frameworks como o Swagger, que é um framework open source que apoia o desenvolvedor no desenho, documentação e especificação de suas Api's.


Conclusão

Se você leu atentamente todos os itens citados acima, você ja tem a total certeza que para construir uma API Rest de alta qualidade, não basta apenas conhecer uma linguagem de desenvolvimento, é preciso conhecer muito bem o protocolo HTTP e um conjunto de padrões que com certeza elevam o nível de sua API.


Fontes:

Serviços RESTful de DataServer no RMFontes:

https://api.totvs.com.br/guia

...

https://wssilva-willian.medium.com/design-de-api-rest-9807a5b16c9f

https://imasters.com.br/desenvolvimento/definicao-restricoes-e-beneficios-modelo-de-arquitetura-rest

https://martinfowler.com/articles/richardsonMaturityModel.html

https://docs.aws.amazon.com/pt_br/apigateway/latest/developerguide/api-gateway-caching.html