REST não é JSON

Atualmente, é muito comum ouvirmos falar sobre APIs REST (REpresentational State Transfer). APIs REST são anunciadas como uma alternativa com maior interoperabilidade e facilidade de uso. O formato JSON (JavaScript Object Notation) de serialização de dados é comumente associado à APIs REST, de modo que ambos os conceitos se confundem na cabeça das pessoas.  Esta postagem pretende esclarecer as diferenças entre ambos os conceitos e como eles estão relacionados, facilitando o uso e construção de APIs REST.

REST ? JSON ? O que são ? Onde vivem ? De que se alimentam ?

JSON

JSON é um formato para transferência de dados entre programas. Foi primeiramente especificado e popularizado por Douglas Crockford — um evangelista do Javascript e atualmente engenheiro sênior no Paypal — no início dos anos 2000.

Documentos JSON têm diversas vantagens entre as quais encontra-se a legibilidade (seres humanos conseguem ler facilmente um documento JSON). Mensagens em JSON também são menores que mensagens equivalentes codificadas em outros formatos (olá XML !!!!). Uma outra vantagem importante é que, graças a popularidade do formato, navegadores costumam ter seus parsers de JSON escritos de modo nativo. O que acarreta melhor desempenho.

REST

Em 2000,  Roy Field definiu o modelo REST, em sua tese de doutorado chamada Architectural Styles and the Design of Network-based Software Architectures. Sua principal motivação foi a descrição de como uma aplicação web — ou API —  deve se comportar. A justificativa fora que, seguindo estas recomendações, aplicações apresentariam requisitos não-funcionais importantes, como  escalabilidade, modificabilidade, confiabilidade, entre outros.

O elemento primordial de uma API Rest é o recurso.  Pode-se traçar um paralelo entre recursos e objetos, do paradigma OO (Orientado a Objetos): ambos representam conceitos concretos e abstratos (i.e. coisas) em um sistema; e, ambos são compostos por atributos, associações e métodos. Porém, ao contrário de objetos, recursos têm seus métodos previamente definidos pelo protocolo HTTP.  

A identificação de um recurso dentro de um sistema se dá através de URIs (Uniform Resource Identifier — identificador uniforme de Recursos). O padrão de codificação dos dados trafegados é definido através de cabeçalhos na requisição e na resposta (Accept e Content-Type).

Os mecanismos de identificação e codificação aliados aos métodos do protocolo HTTP definem uma interface uniforme para acesso (e manipulação) de recursos. Notavelmente, não existe nenhuma regra que dita que APIs Rest devam usar JSON como meio de transferência de dados. JSON é apenas uma das possíveis formas de transferência. É perfeitamente legal, e interessante, do ponto de vista de um vendor, o suporte a diferentes formas de transferência de dados (JSON, XML, YAML) em uma mesma API.

Tá, mas e daí ?

Conforme discorrido, um dos pilares de uma API RESTful é a uniformidade das interfaces. Bibliotecas e frameworks dependem dessa semântica para operar de maneira correta. A integração se torna problemática quando o desenvolvedor de uma API decide não adotar a semântica esperada.

Existem algumas características cuja presença normalmente indica equívocos na adoção do paradigma REST. Entre elas, pode-se citar a presença de verbos nas URLs e a falha na adoção dos códigos de erros definidos pelo protocolo HTTP.

Presença de verbos nas URL

A presença de verbos nas URL (e.g. http://minha.api.com.br/usuarios/45/bloquear) indica que o desenvolvedor não adotou a recomendação na qual uma URL identifica um recurso. É provável também que os verbos HTTP não foram utilizados da maneira correta e suas características básicas (idempotência, cacheabilidade e etc.) não foram honradas.

Uma modelagem mais adequada consiste na criação de um recurso bloqueio, aninhado ao usuário (http://minha.api.com.br/usuarios/45/bloqueio). Criações de bloqueios seriam realizadas através de requisições POST à URL (que retornariam código 201 caso a criação fosse bem-sucedida). Verificação de bloqueios seriam realizadas através de GETs. Os códigos de retorno (200 e 404, respectivamente) indicariam se o usuário está bloqueado ou não. Desbloqueios se resumiriam a requisições DELETE que retornariam o código 204 (ou 200, caso seja necessário o retorno de alguma informação extra) caso fossem bem sucedidas.

Falha na adoção de códigos de erro do protocolo HTTP

Outro mau-cheiro comumente encontrado reside no tratamento de erros. De maneira análoga aos verbos, o protocolo HTTP provê uma gama de erros com semântica pré-definida que são amplamente usados por frameworks e bibliotecas de integração.

Um exemplo é o Ember Data, componente do Ember.js que implementa repositórios de dados, conforme definido pela abordagem DDD (Domain Driven Design). Buscas no backend que retornem o código 404 são interpretadas como ausência do recurso e transparentemente tratadas pelo framework. Já buscas que retornem código 200 são tratadas como entidades válidas e retornadas ao código cliente (código consumindo a API).

A grosso modo, não existe como um framework distinguir entre um recurso sem nenhuma propriedade e a ausência de um recurso.  Logo, o desenvolvedor é obrigado a escrever código de tratamento de erro mais rebuscado e deixa de aproveitar os recursos de tratamento de erro do framework. Além disso, um framework pode adotar estratégias de cacheamento no intuito de diminuir o número de requisições (e.g. entidades podem ser buscadas uma única vez e seu conteúdo armazenado localmente por um tempo estabelecido). Neste caso, corre-se o risco de se cachear uma entidade vazia.

Algumas vezes a semântica de um código de um erro não é insuficiente para desenhar um panorama de sua causa. O erro 400 (BAD_REQUEST) é normalmente utilizado para indicar problemas de validação da entrada de um serviço (uma data inválida, por exemplo). Nesse caso, indica-se o enriquecimento da respostas de erros (no exemplo anterior, poderia-se enviar uma lista contendo os campos inválidos e uma breve explanação das razões para sua invalidez).

Conclusão

Apesar de serem conceitos distintos, muitas vezes não fica claro para o desenvolvedor o que caracteriza uma API como REST. Comumente APIs são anunciadas como APIs REST APIs que não seguem este paradigma. Estas APIs seguem o modelo RPC tradicional e usam JSON para a transferência de dados. É importante que tenhamos em mente o real significado destes conceitos. Caso contrário, corre-se o risco de gerarmos expectativas erradas sobre o funcionamento das coisas. O que por fim gera retrabalho e insatisfação da equipe e do cliente.

P.S. Veja também o post Boas Práticas para Desenvolvimento de APIs REST, onde são descritas alguns padrões para a escrita de API Rest.

 

Por BRUNO SOFIATO

Desenvolvedor com 17 anos de experiência. Começou a programar com 8 anos em um Apple II. Mestrando. Linhas de pesquisa compreendendo sistema de tipos e extensões de linguagem. Viciado em jogos, musica e aviação.

Postado em: 21 de agosto de 2017

Confira outros artigos do nosso blog

[Webinar] Profile de aplicações Java com Oracle Mission Control e Flight Recorder

24 de julho de 2017

Danival Calegari

Criando Mocks de serviços REST com SoapUI

27 de junho de 2017

Monise Costa

JavaScript 6: diferença entre var, let e const

09 de maio de 2017

Otávio Felipe do Prado

Iniciando com o POSTMAN

17 de abril de 2017

Arthur Fritz Santiago

Deixe seu comentário