REST é um estilo de arquitetura ou até mesmo um Design Patterns, que tem uma série de critérios que devem ser seguidas no processo de sua criação


Restriçõ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.

    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)

    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.

    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 Method Idempotente Safe
    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.


    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.


    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-1

    Este documento tem por objetivo demonstrar o padrão e as dificuldades que poderão ser encontradas durante a implementação de APIs para consumo de frontends interno e externo.

    Documentação para padronização: 3. Elaborando uma Mensagem Padronizada - REST/JSON

    Importante!

    Não deverá implementar rotas para CRUD de entidades do TCGI. 
    Para utilização dos serviços de CRUD é recomendado a utilização dos serviços RESTFULL RM.
    Para conhecer todos os serviços do RM: 4. Serviços RESTful no RM

    Para saber qual os dataservers e verbos disponíveis para cada dataserver, poderá ser consultado através da lista generica do TCGI.
    http://{dominio}:{ApiPort}/RMSRestDataServer/service/imobiliario

    Exemplo - POST - Contrato de Venda
    url
    http://localhost:8051/rmsrestdataserver/rest/ImbVendaContratoData
    
    Headers
    Authorization: Basic bWVzdHJlOnRvdHZz
    codcoligada: 1
    codsistema: X
    Content-Type: application/json
    
    Body - selecionar "raw" - JSON (application/json)
    {
    "CODCOLIGADA" : 1,
    "COD_SIT_VENDA" : 15,
    "NUM_VENDA" : -1,
    "COD_PESS_EMPR" : "101",
    "DAT_CAD_VENDA" : "2011-01-01",
    "VR_TOT_VENDA" : "100000",
    "XITEMVENDA": [{
                   "NUM_VENDA" : -1,
                   "COD_PESS_EMPR" : "101",
                   "NUM_UNID" : "01",
                   "NUM_SUB_UNID" : "000302",
                   "VR_ITEM" : 100000.0000
       }]
    }

    Classe Controller

    - Classe controller onde conterá as rotas e verbos para consumo da API deverá ser criada no projeto RM.IMB.API na pasta Common obrigatoriamente
       a LIB monta o swagger baseada nas informações da dll com final API.
    - A classe de controller deverá receber minimamente os atributos 
      [RoutePrefix("imb/v1/comissao")] //rota padrão de todos os serviços disponibilizados pelo TCGI 
      [RMSController("ImbComissaoRegraServer")]  
      [AllowAnonymous]
      [RMSLicense(IgnoreLicense = true)] //Licenças diferenciadas PDC, PI, APP
    - Método que fazem parte das rotas na classe de controller devem estár como publico e receberem minimanente os atributos
      (Método de exempo da classe controler: public ImbComissaoRegraEntity GetReadRecord(int idcorretor){ regras do metodo } )
    [HttpGet] 
    [Route]
     - Atributo utilizado para determinar se deverá citar no caminho da API o nome ou não, se deverá passar valores na assinatura diretamente ou no caminho.

            Exemplo: [Route] - não informando nenhum caminho ou parametro - deve seguir o método acima - http://{dominio}:{ApiPort}/api/imb/v1/comissao?idcorretor=1
                            [Route("corretores")] - está informando que a rota deverá conter o caminho "corretores" - http://{dominio}:{ApiPort}/api/imb/v1/comissao/corretores
                            [Route("corretor/{idcorretor}")] - deverá informar o caminho e a chave diretamente.  - http://{dominio}:{ApiPort}/api/imb/v1/comissao/corretor?idcorretor=1
                            [Route("corretor/{idcorretor}")] - deverá informar o caminho e a chave diretamente. - http://{dominio}:{ApiPort}/api/imb/v1/comissao/corretor/1
      
    - Deverá ser criada a classe model que será utilizada no controler, está é o modelo utilizado para setar os valores e fazer transformação em Json.
      Nesta classe as variaveis declaradas para recebimento dos valores deverão conter os atributos para transformação da classe modelo de objeto para um tipo Json.
      [JsonProperty("IDCOMISSAO")]


    Importante: Deletar o _Broker.dat para ser regerado após criar todas as classes envolvidas no processo de disponibilização da API.


    Swagger

    Para saber se seu controller ou mesmo a rota foi publicada corretamente no serviço do host da aplicação você poderá acessar o caminho http://{dominio}:{ApiPort}/api/swagger/, a lista das apis e rotas demoram para serem carregadas
    (Dica: para carregar mais rápido, antes de chamar o swagger, vá até a pasta BIN da aplicação e apague todas as dlls "RM.*.API.dll" com exceção da dll RM.IMB.API.dll, assim o carregamento será mais rápido).
    Após serem carregadas, pesquise pelo nome do seu controller e depois pela rota. Para saber mais sobre swagger Totvs clique aqui.

        Importante: O Host da maquina que está sendo verificado o serviço, deverá estar rodando com autorização de administrador, atenção com o firewall.

    Video demonstração de verificação da API:

    Swagger UI - Verificando API controller está disponível.mp4


    Testando o consumo dos serviços da API

    1 - POSTMAN
        - Você pode utilizar autenticação "Basic Auth" para este formato deverá informar 'Username' e 'Password' campos que abriram logo abaixo na tela após selecionar a opção informada.
        - Recomendamos utilizar a autenticação 'Bearer', caso a opção não apareça no seu postman, poderá digitar manualmente na aba 'Headers' na opção 'Key' o descritivo "Authorization" e em 'value' "Bearer TOKEN ENCONTRADO APÓS CONSUMO DO SERVIÇO DE FORNECIMENTO DO TOKEN", para geração do token utilize a API http://localhost:8055/api/connect/token, quando for utilizar o serviço para geração do token, deverá utilizar a autenicação basica, Para saber sobre Token Totvs RM.

    Postman - Consumindo a API após estar visivel no Swagger.mp4



    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:

    4. Serviços RESTful no RM

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

    https://blog.geekhunter.com.br/sua-api-nao-e-restful-entenda-por-que/

    https://www.alura.com.br/artigos/rest-principios-e-boas-praticas

    https://www.brunobrito.net.br/api-restful-boas-praticas/

    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

    • Sem rótulos