Anda di halaman 1dari 38

11/3/2014 Construindo uma RESTful API Parte 1

www.devmedia.com.br
[verso para impresso]
Link original: http://www.devmedia.com.br/articles/viewcomp.asp?comp=29904

Construindo uma RESTful API


Parte 1
Este artigo apresenta o estilo REST de construo de web
services, bem como as melhores prticas comumente
adotadas na criao de uma RESTful API.

Demais posts desta srie:

RESTful API: construindo uma API simples Parte 2

Artigo no estilo Curso

Fique por dentro


Este artigo apresenta o estilo REST de construo de web services, bem como as
melhores prticas comumente adotadas na criao de uma RESTful API. Seguindo as
prticas analisadas aqui, o leitor poder melhorar a performance, a manutenibilidade e
a usabilidade das APIs projetadas, tornando-as completas e intuitivas para os
desenvolvedores que as utilizaro.

Este tema til para desenvolvedores que precisem criar uma API pblica ou privada
para expor dados e funcionalidades de um sistema web para outras aplicaes, sejam

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 1/38
11/3/2014 Construindo uma RESTful API Parte 1

elas web, mobile ou desktop.

medida que um sistema web vai evoluindo, comum que se torne necessrio uma nova
forma de se comunicar com ele. Comumente, sero humanos que o usaro em um
browser para acessar e modificar seus dados. Porm, pode chegar o momento em que
desejamos tornar possvel que outras aplicaes se comuniquem com nosso sistema,
seja com o intuito de disponibilizar outros clientes (muitas vezes nativos a alguma
plataforma, como o Android) ou para expor informaes de acordo com os requisitos de
outros desenvolvedores. Quando chega esse momento, precisamos de web services para
prover acesso a esses dados.

Para entender melhor, exploraremos o exemplo do Facebook. Devido ao seu grande


crescimento como rede social, ele encontrou diversas oportunidades que o ajudaram a
crescer ainda mais. Entre elas, podemos destacar duas que envolvem a criao de web
services: a expanso do mercado mobile, exigindo aplicaes nativas para tais
dispositivos, e a expanso de suas funcionalidades atravs de aplicaes de terceiros.

Essas oportunidades tm em comum a necessidade de web services para suprir


informaes para as aplicaes externas. Afinal, a web comum baseada em HTML, que
possibilita uma boa interao do sistema com pessoas. Entretanto, quando a aplicao
precisa interagir com outras aplicaes, essas pginas no so uma boa opo.

Assim como o Facebook, h momentos em que necessitamos desenvolver web services


para nossas aplicaes. Nesses momentos, duas siglas vm nossa mente: SOAP e
REST. Muitos vo conhecer melhor SOAP, que significa Simple Object Access Protocol e
tendero a escolh-lo sobre o REST, que significa Representational State Transfer.
Discutir qual o melhor est fora do escopo deste artigo. Porm, considerando os
motivos do Facebook, que tambm podem ser os seus, justificaremos o porqu da
escolha do REST.

Para iniciar essa discusso, vamos primeiro rever os motivos do Facebook. Em resumo,
ele desejava prover acesso para aplicaes clientes, principalmente mobile, e a outros
sistemas de terceiros. Nesse contexto, analisaremos a seguir o que torna o REST a
melhor opo:

1. O SOAP uma especificao de um protocolo estruturado em XML. Devido ao


tamanho de suas mensagens, elas naturalmente ocupam mais rede, o que pode ser um

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 2/38
11/3/2014 Construindo uma RESTful API Parte 1

problema para aplicaes mobile;

2. A complexidade na comunicao com um web service SOAP tambm um problema


para aplicaes mobile e HTML5, visto que so necessrias bibliotecas especficas,
utilizao de geradores de cdigo e ainda a manuteno do cdigo gerado nas diferentes
plataformas;

3. O SOAP foi construdo com o pensamento da comunicao entre servidores, em que


assumido que eles so naturalmente seguros. No se pode garantir que uma aplicao
rodando em um dispositivo de um usurio possua tal segurana;

4. O REST mais simples. Foi projetado para ser usado em clientes magros, o que o
torna ideal para utilizao em dispositivos com capacidades limitadas;

5. As respostas do REST so cacheveis, diferente do SOAP. Isso d um grande


aumento de performance em clientes simples;

6. Enquanto o SOAP utiliza apenas XML, o REST pode se comunicar atravs de diversos
formatos, sendo JSON o mais usado. Por ser um formato menos verboso e normalmente
menor, a transferncia de dados com o uso de JSON causa uma carga menor na rede,
alm de ser mais facilmente consumido por clientes construdos com qualquer linguagem,
em especial HTML5.

Como podemos verificar, no contexto apresentado, a melhor opo o REST. Mas isso
no significa que ele perfeito e fcil de implementar. Consumir um web service bem
construdo e bem documentado que utiliza REST fcil e d grande produtividade para o
desenvolvedor.

Porm, o mesmo no se aplica para a sua construo. Veremos que so muitos os


detalhes a serem considerados na construo de uma boa RESTful API para outros
desenvolvedores.

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 3/38
11/3/2014 Construindo uma RESTful API Parte 1

REST
Diferente do SOAP, que uma especificao, o REST algo mais abstrato: um estilo
arquitetural. Ele formado por um conjunto de regras no topo do protocolo HTTP que
foram comunicadas pela primeira vez por Roy Fielding em sua tese de doutorado. Depois
de seu surgimento, comeou a se tornar uma alternativa mais leve de comunicao entre
computadores (cliente e servidor).

Para entend-lo, devemos saber cada uma de suas seis regras. Para ser considerado
REST, o web service deve ser ou possuir: Interface uniforme, Stateless, Cachevel,
Cliente-Servidor, Sistema em camadas e Cdigo sob demanda. Veremos em detalhes
cada uma delas a seguir.

Interface uniforme
Essa regra define que deve haver uma interface uniforme de comunicao entre o cliente
e o servidor. O objetivo dela torn-los independentes um do outro. Isso facilita a
criao de uma API, ou seja, um contrato a ser seguido por terceiros na utilizao da
mesma. Dessa forma, assim como acontece com interfaces no Java, os utilizadores no

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 4/38
11/3/2014 Construindo uma RESTful API Parte 1

precisam saber os detalhes da implementao.

Em cima dessa regra, so definidos alguns princpios. O primeiro deles que o REST
dever ser baseado em recursos identificados por URLs. Diferente de SOAP, que
baseado em aes, como obter produto, o REST baseado no recurso, deixando a
definio das aes para os mtodos HTTP. Portanto, quando quisermos obter um
recurso, como um produto, faremos uma requisio GET para a URL que o localiza.

Assim, importante entendermos que as URLs sero definidas por substantivos e no


por verbos, salvo quando for necessrio fazer algum clculo ou algo que no esteja
vinculado a um recurso no servidor. O motivo disso bem simples: tornar a interface
simples. A Listagem 1 mostra exemplos de URLs para um recurso Produto que no
seguem esse padro e a Listagem 2 mostra exemplos que o seguem.

Listagem 1. Exemplos de URL que no seguem os princpios do REST.

/listarProdutos = URL para listar todos os produtos


/obterProduto/1 = URL para obter o produto 1
/criarProduto = URL para criar produto
/deletarProduto = URL para deletar produto

Listagem 2. Exemplos de URL que seguem os princpios do REST.

/produtos = URL para aes sobre recursos do tipo Produto


/produtos/1 = URL para aes sobre um produto especfico

Em ambas as listagens foram mostradas apenas o CRUD bsico desse recurso. Porm, a
Listagem 2 parece incompleta. Afinal, onde definimos as aes? Elas so definidas
utilizando os mtodos do protocolo HTTP: GET, POST, PUT, DELETE e HEAD. Veremos
mais a frente como cada um desses mtodos usado, mas pode-se adiantar que os
quatro primeiros sero traduzidos nas operaes de CRUD.

Ainda observando os exemplos da Listagem 2, podemos ter outra dvida: por que
utilizar o plural? Bem, essa resposta bem direta: simplicidade novamente. Utilizando o
plural, as operaes de leitura para uma lista ficam naturais, mas parece menos natural

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 5/38
11/3/2014 Construindo uma RESTful API Parte 1

quando nos referimos a uma nica instncia do recurso. No entanto, por simplicidade,
mantemos todas as URLs de determinado recurso com a mesma raiz (parte inicial da
URL), que por padro est no plural.

Outra definio importante que no obteremos recursos atravs dessas chamadas ao


servidor, mas sim suas representaes. Por isso a sigla REST significa Representational
State Transfer. Transferimos do servidor para o cliente e vice-versa representaes de
um recurso, sendo eles representados de diversas formas. Usa-se predominantemente
JSON, mas tambm comum represent-los no formato XML.

Essa ideia de representaes de recursos tambm pode ser identificada na Web. Nela, o
usurio localiza um recurso por uma URL. Esse recurso mostrado de forma legvel para
humanos atravs de uma representao em HTML, a qual interpretada pelo navegador
e o mesmo cria uma visualizao para o usurio. Aqui estamos fazendo algo parecido. A
diferena que usamos representaes a serem lidas e interpretadas por outras
aplicaes. Afinal, diferente de seres humanos, elas no precisam da aparncia visual, e
sim dos dados.

Podemos levar essa comparao adiante introduzindo mais um princpio definido pelo
REST: HATEOAS. Essa sigla significa Hypermedia as the Engine of Application State.
Esse princpio define que o estado da aplicao, ou seja, o estado dos recursos desta,
transferido entre o cliente e o servidor na forma de hypermedia: hypertexto com
hyperlinks.

Isso significa que, dada a requisio por um recurso, tanto o seu link quanto os links dos
recursos relacionados sero retornados no corpo da resposta para essa requisio.
Assim, aplicaes clientes podem ser guiadas a outros recursos atravs dos hyperlinks
fornecidos pelo prprio resultado de uma chamada API.

Se compararmos isso com a Web que conhecemos, podemos perceber que o HTML que o
servidor retorna para nosso navegador tambm uma hypermedia. Nela esto links que
usamos para encontrar outros recursos relacionados, o que faz com que possamos ser
guiados para outros recursos facilmente sem precisarmos necessariamente saber a URL
que os localiza.

Para exemplificar isso no contexto de REST, imagine que estamos utilizando a API do
Facebook para obter as postagens de um usurio. Como esperado que tivessem
diversos itens como resultado, natural pensarmos numa paginao dos mesmos.
Ento, quando fazemos a requisio, podemos ver que o prprio resultado j nos
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 6/38
11/3/2014 Construindo uma RESTful API Parte 1

retorna um hyperlink para a prxima pgina de resultados. Esse apenas um exemplo


real usado para mostrar como as representaes dos recursos so interligadas na forma
de hypermedia. Isso feito atravs da utilizao de URLs para identificar os recursos.

O ltimo princpio a ser apresentado dentro dessa regra de Interface Uniforme o que
diz respeito s mensagens serem autodescritivas. Isso significa que as mensagens
devem trazer informaes sobre o formato de representao a ser utilizado, a
possibilidade de fazer cache dos dados, entre outras informaes que as tornam
completas.

Veremos mais sobre os formatos mais adiante. No momento, continuaremos expondo as


regras definidas pelo REST.

Stateless
Essa uma das regras mais importantes do REST. Ela dita que cada requisio dever
conter todas as informaes relevantes para ser processada. Ou seja, no deve haver
manuteno de estado entre as requisies. Caso haja alguma manuteno de estado,
esse dever ser mantido pelo cliente e enviado a cada nova requisio.

Assim, a nica responsabilidade do servidor utilizar os dados recebidos na requisio,


fazer o processamento necessrio e retornar tudo que for pertinente ao cliente.

Isso pode parecer estranho a princpio para quem est acostumado a desenvolver para a
Web, em que sempre possumos um estado guardado no servidor para cada cliente.
Porm, essa regra abre caminho para obter uma enorme escalabilidade, visto que o
servidor no precisar manter uma sesso e se comunicar utilizando-a.

Com isso, poderamos criar clusters de servidores espalhados e ter um balanceador de


carga sem nos preocuparmos se a requisio do usurio ser tratada por um servidor
que possui seus dados de sesso.

Veremos mais a frente que essa regra descumprida em alguns casos, como o caso da
three-legged OAuth, que uma especificao de segurana. Mas essa regra deve ser
sempre seguida, a no ser em casos especiais.

Cachevel
O servidor, sempre que possvel, dever indicar ao cliente a possibilidade do mesmo fazer
cache dos resultados retornados. Essa capacidade de fazer cache reduz o trfego de

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 7/38
11/3/2014 Construindo uma RESTful API Parte 1

dados entre o cliente e o servidor, melhorando a escalabilidade do servidor e melhorando


a performance de ambos. Veremos mais a frente como podemos utilizar uma tcnica
baseada em ETag para se obter tal capacidade.

Cliente-Servidor
Apoiado na regra da interface uniforme, esta a regra que separa as responsabilidades
do cliente e do servidor. Ela indica que de responsabilidade do servidor o
armazenamento dos dados, o que aumenta a portabilidade do cliente. Tambm diz que
de responsabilidade exclusiva do cliente a apresentao da interface com o usurio, bem
como a manuteno da sesso dele, o que torna os servidores mais escalveis.

Assim, o cliente e o servidor podero ser desenvolvidos de maneira independente,


enquanto a interface de comunicao entre eles permanecer inalterada.

Sistema em camadas
Essa regra abre possibilidade para a diviso do servidor em um sistema em camadas,
visto que ela afirma que a interface da API deve funcionar de tal forma que o cliente no
consiga diferenciar se est sendo atendido pelo servidor final, um servidor que utiliza os
servios do final ou mesmo se o servidor atual o mesmo que atendeu as requisies
anteriores.

Assim, a escalabilidade mais uma vez aumentada, visto que podemos configurar um
cluster de servidores conectados por um balanceador de carga, sem que o cliente precise
notar isso.

Cdigo sob demanda


A regra que diz que o servidor poder estender as funcionalidades do cliente atravs da
transferncia de lgica a ser executada pelo mesmo, como um script em JavaScript a ser
executado pelo cliente, a nica regra opcional. Ela apenas indica a possibilidade do
servidor fazer isso, mas no torna tal funcionalidade necessria para definir um servio
como REST.

Com isso, conclumos as seis regras que compem o estilo arquitetural do REST. Nosso
prximo objetivo entender melhor como as aes sobre os recursos so vinculadas aos
mtodos HTTP.

HTTP Methods
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 8/38
11/3/2014 Construindo uma RESTful API Parte 1

Como foi discutido anteriormente, os recursos so identificados por URLs com a mesma
raiz, que construda com o nome do recurso no plural. A partir disso, todas as aes
sobre esses recursos so feitas utilizando mtodos HTTP: GET, POST, PUT, DELETE e
HEAD. Isso mostra que, diferente da Web comum que conhecemos, o REST faz um uso
mais avanado das capacidades do protocolo HTTP, utilizando os outros mtodos no
suportados nela, visto que a mesma possui apenas requisies dos tipos GET e POST.

Antes de mapearmos cada um desses mtodos para suas respectivas aes sobre um
recurso, vamos falar sobre um atributo que alguns deles tm em comum: a
idempotncia.

Idempotncia
Uma ao idempotente aquela que produzir o mesmo resultado independente de
quantas vezes ela seja executada. Isso significa que quando executarmos uma ao
idempotente mltiplas vezes em um recurso, seu estado ficar de tal forma como se
tivssemos executado apenas uma vez.

Esse atributo importante, pois h momentos em que no temos certeza se nossa


requisio chegou ao servidor. Isso pode acontecer, por exemplo, se a internet cair
durante a requisio. No saberemos se o servidor executou nossa requisio e no
conseguiu responder devido ao problema de comunicao ou se nossa requisio nem
mesmo chegou ao servidor.

Se a ao que estamos tentando executar for idempotente, podemos simplesmente


repetir a requisio, visto que esse tipo de ao garante a manuteno do estado do
recurso como se uma nica requisio tivesse sido enviada.

Esse atributo muito importante, mas no est presente em todas as aes possveis
sobre um recurso. medida que explorarmos cada um dos mtodos HTTP com suas
respectivas aes, indicaremos se o mesmo possui ou no idempotncia.

HTTP GET
O mtodo GET um dos que deixa mais claro, pelo seu prprio nome, qual tipo de
operao ele realiza. Naturalmente, esse tipo de requisio mapeada para a operao de
leitura do recurso. O resultado para ela que uma representao, em determinado
formato, do recurso, retornada pelo servidor no corpo da resposta.

Temos algumas opes nesse tipo de requisio. Podemos requisitar uma nica instncia
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 9/38
11/3/2014 Construindo uma RESTful API Parte 1

de um recurso, utilizando seu ID na URL como visto anteriormente, e tambm requisitar


uma coleo de recursos. Em ambos os casos, podemos dizer ao servidor em qual
formato queremos a representao desse recurso, sendo em JSON ou XML, por
exemplo, dependendo da disponibilidade desses formatos no servidor.

Tambm veremos mais a frente que uma boa prtica a ser implementada a possibilidade
de paginao da coleo de recursos. Alm disso, veremos em breve como selecionar os
campos desejados, fazer um filtro na recuperao, entre outras boas prticas.

Ainda sobre a requisio do tipo GET, por ser uma operao de leitura, naturalmente
idempotente, visto que ela nem mesmo altera o estado do recurso. Portanto, caso haja
uma falha de conexo, podemos simplesmente repetir a requisio sem se preocupar
com qualquer efeito colateral.

Mais detalhes sobre as respostas para essas requisies, incluindo o status HTTP
retornado pelo servidor em diferentes situaes, sero vistos adiante.

HTTP DELETE
Assim como o GET, o nome do DELETE tambm bem intuitivo e deixa bem claro o que
ele faz: deleta uma ou mais instncias de um recurso. Essa requisio pode ser
executada para uma instncia nica utilizando o ID na URL ou para todas as instncias
atravs da raiz do recurso. Tambm possvel deletar mltiplos recursos especficos a
partir de uma filtragem dos resultados, o que ser visto mais a frente.

Porm, por ser uma operao crtica, comum que o servidor a disponibilize apenas para
requisies com o ID a ser deletado.

Sendo essa uma operao que remove totalmente um recurso, ela idempotente. A
nica diferena que pode acontecer em mltiplas chamadas que as chamadas
consecutivas sero respondidas pelo servidor com uma mensagem que indique que o
recurso no foi encontrado. Naturalmente, com essa resposta, o cliente pode inferir que
o recurso foi deletado em uma das requisies anteriores.

HTTP HEAD
O mtodo HEAD um dos menos comuns e normalmente no disponibilizado pelo
servidor. Seu objetivo parecido com o GET, com a diferena que ele retornar apenas
metadados sobre o recurso requisitado, ao invs de trazer suas representaes
completas. Essa requisio poderia ser usada para saber informaes sobre uma coleo
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 10/38
11/3/2014 Construindo uma RESTful API Parte 1

de recursos, como a quantidade total, e tambm para se obter informaes sobre um


recurso especfico, como a data da ltima modificao.

Deste modo, como o GET, essa requisio tambm idempotente, visto que no causa
nenhuma alterao de estado nos recursos.

HTTP POST
O mtodo POST usado na Web comum para se criar e atualizar um determinado
recurso atravs de um formulrio. No contexto de REST, ele usado de forma similar.
POST possui duas funes: criar um recurso (sem especificar o ID do mesmo, de forma a
deixar que o servidor o gere) e fazer uma atualizao parcial do mesmo.

Por atualizao parcial, entendemos como uma atualizao em que apenas alguns campos
de uma instncia de recurso so modificados, deixando os outros sem qualquer
modificao.

Quando utilizamos esse mtodo para criar um recurso, deixando que o servidor gerencie
seu ID, naturalmente precisamos saber com qual ID ele foi criado. Portanto, o servidor
deve responder a essa requisio com a localizao do recurso, sendo essa a URL que
unicamente o localiza.

Atravs dessa URL, sabemos a localizao e o ID do mesmo, que so informaes


importantes para continuarmos interagindo com ele. Pode ser, tambm, que o servidor
adicione na resposta a representao desse novo recurso. Isso pode muitas vezes ser
intil, j que o cliente possui a representao que acabou de ser criada no servidor, mas
pode fazer sentido em alguns momentos em que tal recurso possua outros campos
gerados pelo servidor.

Por sua natureza de criao de um recurso novo ou atualizao parcial de um recurso


existente, esse mtodo no idempotente. Se repetirmos a requisio de criao,
teremos mltiplos recursos criados com estado duplicado. No caso da requisio de
atualizao parcial, podemos deixar o recurso inconsistente se outra requisio desse
tipo for realizada por outro cliente em paralelo. Portanto, esse mtodo deve ser utilizado
com cuidado, devido sua natureza no idempotente.

HTTP PUT
O mtodo PUT no utilizado na Web comum, mas podemos imaginar seu significado
pelo seu nome. Atravs desse nome, imaginamos que ele coloca algo no servidor.
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 11/38
11/3/2014 Construindo uma RESTful API Parte 1

Assim, ele possui duas funes: fazer uma atualizao completa de determinado recurso
(especificado pela URL) e criar um recurso especificando o ID.

Como comum que seja de responsabilidade do servidor a criao do ID de seus


recursos, sua segunda funo menos comum e pode no ser disponibilizada pelo
servidor.

Quando falamos sobre uma atualizao completa, estamos especificando que os valores
de todos os campos do recurso sero alterados com essa requisio. Portanto, comum
que ela acontea depois de uma requisio do tipo GET que obtenha todos os campos
atuais e ento o usurio tem a chance de modific-los antes que eles sejam enviados ao
servidor.

Se o servidor disponibilizar a operao de criao de um recurso com seu ID, as


requisies de atualizao e criao ficam idnticas, fazendo o papel de: atualize se existir
ou crie caso contrrio. Nesse caso, no necessrio que o servidor responda com a
localizao do recurso, visto que o ID foi especificado pelo cliente. Mas pode ser que ele
responda com o estado atual do recurso, se for pertinente.

Diferente do POST, esse mtodo sempre modifica completamente o estado de um


recurso localizado em determinada URL. Isso impede que haja inconsistncias no estado
e que mltiplos recursos sejam criados por acidente. Portanto, essa operao
idempotente.

Como podemos ver, o REST utiliza muito bem os mtodos HTTP, separando as
responsabilidades das aes sobre os recursos para cada um desses mtodos. Mas, alm
disso, ele tambm faz grande uso dos headers do HTTP, do status da resposta, dos
parmetros passados na query string, entre outros. Tudo isso ser visto a seguir.

HTTP Status
Quando falamos dos status do HTTP, nos lembramos dos status clssicos usados na
Web: 200 OK, 404 Not Found, 500 Internal Server Error, entre outros. No geral, a no
ser que haja um erro no servidor, o usurio tente uma URL inexistente ou algum outro
caso especfico, o servidor sempre responde com 200 OK, mostrando possveis erros
para o usurio dentro da prpria pgina HTML. Isso acontece porque estamos nos
comunicando com humanos e a melhor forma de mostrar resultados de uma requisio
para ele com uma pgina bem apresentada.

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 12/38
11/3/2014 Construindo uma RESTful API Parte 1

Isso no verdade quando queremos nos comunicar com outros computadores. Nesse
caso, fazemos uso intenso dos status disponveis no HTTP para facilitar o tratamento do
lado cliente. Mais a frente, veremos que uma boa prtica tambm incluir algumas
informaes extras na resposta quando houver uma situao inesperada, para que o
desenvolvedor do software cliente do web service entenda a situao.

Porm, devemos sempre utilizar os status disponveis pelo protocolo HTTP em nossas
respostas.

Para dar uma ideia melhor sobre o uso dessa importante capacidade, mostraremos a
seguir alguns dos principais status HTTP junto com uma explicao sobre onde
poderamos us-los.

200 OK
Esse o status mais comum e que usado na maioria das respostas de requisies bem
sucedidas. Podemos retorn-lo quando as seguintes requisies procedem com sucesso:

1. GET de uma instncia ou coleo de recursos. Esse status indica que a representao
desejada se encontra no corpo da resposta;

2. DELETE sobre um ou mais recursos. Essa resposta significa que os recursos foram
encontrados e deletados do servidor;

3. PUT na criao com ID especificado ou na atualizao de determinado recurso;

4. POST na atualizao completa de determinado recurso.

201 Created
Quando um recurso criado com sucesso, retornamos esse status e adicionamos um
header na resposta chamado Location. Esse header conter uma URL para o novo
recurso. Esse status usado basicamente na criao de um recurso sem a especificao
do ID atravs de POST, apesar de ter sentido o retornarmos tambm quando criarmos
com o ID especificado atravs do PUT.

304 Not Modified


Esse status de grande importncia na utilizao de cache por parte do cliente. Pode-se
usar um cdigo que represente o estado de um recurso e o cliente pode enviar tal cdigo
obtido de uma requisio anterior. Assim, o servidor pode verificar se houve alguma
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 13/38
11/3/2014 Construindo uma RESTful API Parte 1

mudana no recurso e, caso contrrio, retornar apenas esse status, sem nenhum corpo
na resposta, para indicar que o cliente pode fazer uso da resposta obtida anteriormente
e armazenada no cache. Com isso, pode-se evitar o trfego extra na rede.

Veremos mais adiante como criar essa capacidade no servidor para auxiliar os clientes a
fazerem cache das requisies de GET.

400 Bad Request


Esse status, como o prprio nome indica, deve ser utilizado quando o cliente enviar uma
requisio mal formada, seja ela por falta de parmetros, m formao dos parmetros,
entre outras possibilidades.

401 Unauthorized
Apesar de seu nome indicar que o cliente no est autorizado a executar tal requisio, o
nome utilizado no est de acordo com o real sentido desse status. O objetivo dele , na
verdade, indicar que o cliente no est autenticado, ao invs de autorizado. Ou seja, isso
indica que o cliente dever prover uma forma de autenticao e tentar novamente.

Para aqueles que no esto acostumados com os termos utilizados na rea de


segurana, o cliente est autenticado quando ele prova sua identidade ao servidor,
enquanto o fato de estar autorizado indica que, sabendo sua identidade, o servidor
reconhece que ele pode acessar determinado recurso.

A autenticao realizada antes, enquanto a autorizao realizada como forma de


verificao se determinado usurio, j identificado, possui direitos o suficiente. Portanto,
no se confunda com o nome desse status.

403 Forbidden
Esse o verdadeiro status que indica que o cliente, j identificado, no possui direito de
acesso suficiente para realizar determinada ao sobre determinado recurso. Em outras
palavras, o cliente no est autorizado a realizar essa requisio e no deve tentar
novamente, a no ser que venha a obter autorizao para tal.

Unauthorized e Forbidden so usados quando preparamos a segurana da API. Veremos


adiante as boas prticas na implementao dessa segurana.

404 Not Found


http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 14/38
11/3/2014 Construindo uma RESTful API Parte 1

Esse status usado para indicar que um recurso especfico identificado por determinada
URL no foi encontrado. Tal status retornado em requisies GET, DELETE e tambm
na atualizao completa atravs do POST, quando a instncia desejada no encontrada
no servidor.

Com o entendimento dos mtodos utilizados no REST e dos status mais retornados
como resposta pelo servidor, temos o suficiente para construir uma API com o estilo
arquitetural do REST. Porm, se comessemos agora, provavelmente criaramos uma
API pobre e de difcil utilizao, pois ainda no foram apresentadas as boas prticas.
Portanto, o prximo passo apresentar as boas prticas que foram emergindo na
criao de APIs nesse estilo.

Boas prticas na criao de uma REST API


Foi visto at agora as regras do estilo arquitetural REST e como ele utiliza as capacidades
do protocolo HTTP. Oficialmente, isso o REST. Porm, naturalmente foram emergindo
boas prticas que passaram a ser adotadas no desenvolvimento de RESTful APIs. Ao
seguirmos essas prticas, garantimos que nossa API vai possuir boas funcionalidades,
ser de fcil uso para outros desenvolvedores e de fcil manuteno.

Tais prticas definem o design da API, o que influenciar tambm na implementao da


mesma. Daqui em diante, cada uma dessas prticas ser exposta.

Versionamento
Quando projetamos nossa API, definimos uma interface de comunicao a ser utilizada
por outras aplicaes. Podemos comparar essa interface com as clssicas interfaces do
Java, que definem os mtodos, mas sem explicitar a implementao dos mesmos. Os
clientes de nossa API a vero da mesma forma. Eles lero a documentao que especifica
o funcionamento do web service.

Nessa documentao sero especificados quais recursos esto disponveis, quais as URLs
dos mesmos, os parmetros esperados, etc. Atravs dessas especificaes se tem um
contrato de como a API vai funcionar, mesmo sem saber como ela implementada.

Enquanto no houver mudanas nessa interface, pode-se dar manuteno normalmente


no cdigo que a implementa. Porm, pode ser que precisemos mudar essa interface por
algum motivo. Quando isso acontecer, s podemos ter uma certeza: todas as
implementaes de clientes que confiem no contrato estabelecido por ela deixaro de

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 15/38
11/3/2014 Construindo uma RESTful API Parte 1

funcionar. Ento, como podemos lidar com isso?

Para resolver esse problema fazemos um versionamento da interface da API. Assim,


obrigamos o cliente a especificar qual verso ele est invocando. Assim, quando houver
uma modificao na interface, avisamos os clientes e damos um prazo para eles migrarem
para essa nova verso, deixando a verso antiga funcionando por um prazo
determinado. Vale notar que estamos falando aqui de uma mudana de interface e no
de implementao. As mudanas de implementao devero ser transparentes aos
usurios, desde que a interface definida seja respeitada.

Mas o que exatamente a interface, o contrato com o cliente? Esse contrato composto
pela sintaxe das requisies e respostas sobre os recursos. Nessa sintaxe esto
inclusos: a URL do recurso, os headers da requisio HTTP, a estrutura da resposta e
representao do recurso, opes disponveis que alteram de alguma forma o resultado
da requisio, entre outros.

Qualquer alterao que mude a forma de interao com determinado recurso deve ser
versionada, pois tal alterao poder fazer com que as implementaes criadas por
determinado cliente sejam quebradas, vindo a falhar.

Porm, nem toda alterao da interface precisa necessariamente sofrer versionamento.


Se adicionarmos um campo na representao de um recurso, por exemplo, no
afetaremos os clientes existentes, que simplesmente ignoraro tal campo. Portanto,
devemos sempre pensar no quanto uma modificao afeta nossos clientes.

Qualquer alterao na interface que possa fazer com que a implementao do cliente
venha a falhar, dever ser versionada.

Entendido o porqu e quando devemos versionar, podemos nos perguntar como


especificar as verses. Pode-se pensar em criar verses com alto grau de granularidade,
como 1.0.1, 2.1.3, etc. Mas essa no a forma mais recomendada. Ao invs disso,
especificamos nmeros simples, deixando nossas verses na forma v1, v2, etc.

O motivo disso que estamos falando de uma interface e interfaces no devem mudar
com frequncia. Nmeros com alto grau de granularidade do a impresso de que haver
modificaes constantes nas verses e esse no o caso.

Com a numerao de verses decidida, falta especificar como os desenvolvedores


podero comunicar ao servidor qual verso ser empregada para tratar sua requisio.
Nesse ponto, h muita discusso entre aqueles que acreditam que a verso a ser
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 16/38
11/3/2014 Construindo uma RESTful API Parte 1

utilizada da API deve estar na URL e aqueles que acreditam que ela deve ser especificada
como tipo de mdia da requisio, seja no header Accept do HTTP em requisies GET ou
no header Content-Type em requisies POST e PUT.

Antes de argumentar quais das duas deveram utilizar, podemos ver exemplos de
versionamento atravs da URL na Listagem 3 e atravs de tipo de mdia na Listagem 4.

Listagem 3. Exemplos de versionamento atravs da URL.

- GET api.devmedia.com.br/v1/revistas
Accept: application/json
- GET api.devmedia.com.br/v2/revistas/190
Accept: application/json
- POST api.devmedia.com.br/v1/revistas
Content-Type: application/json
Body:
{
nome: Java Magazine,
isbn: 1676-8361
}

Listagem 4. Exemplos de versionamento atravs do tipo de mdia.

- GET api.devmedia.com.br/revistas
Accept: application/vnd.devmedia.revistas-v1+json
- GET api.devmedia.com.br/revistas/190
Accept: application/vnd.devmedia.revista-v2+json
- POST api.devmedia.com.br/revistas
Content-Type: application/vnd.devmedia.revista-v1+json
Body:
{
nome: Java Magazine,
isbn: 1676-8361
}

Podemos ver que nos exemplos da Listagem 3, inserimos um v1 e um v2 no incio da


URL para indicar qual verso da API estamos utilizando. Enquanto na Listagem 4,
modificamos o header que indica qual formato de contedo estamos esperando nas

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 17/38
11/3/2014 Construindo uma RESTful API Parte 1

requisies GET e o header que indica qual o tipo de contedo estamos enviando nas
requisies POST e PUT. Como foi dito, h bastante discusso sobre qual das duas
abordagens mais recomendada.

Um dos argumentos para a utilizao da URL a clareza e a facilidade de se ver qual


verso da API est sendo usada. Essa abordagem tambm facilita os testes da API em
clientes HTTP mais simples, como navegadores. Alm disso, ela adotada nas APIs de
grandes empresas como Google, Twitter, Dropbox, entre outros. Portanto, natural que
os desenvolvedores estejam acostumados com essa forma de versionamento.

Porm, existem muitas crticas para a adoo da URL no versionamento. Uma delas diz
que ela fere o princpio de HATEOAS do REST, visto que links de recursos obtidos e
armazenados anteriormente podero no funcionar mais quando a verso que eles
utilizavam deixar de ser mantida. Tambm dizem que as mudanas de contrato significam
primariamente mudanas nas representaes dos recursos e no exatamente nos
recursos.

Portanto, o lugar certo para se definir a verso no tipo de mdia usado nessa
representao.

Alm desses, existem diversos argumentos e muita discusso acerca da utilizao de


uma abordagem ou de outra. Cada uma delas possui suas vantagens e desvantagens e
cabe ao desenvolvedor escolher qual ser a adotada. Para ajudar na deciso, pode-se ler
sobre o assunto em alguns dos links contidos no final do artigo ou buscar mais opinies
em fruns e artigos.

Seja l qual for a opo escolhida, sempre se deve manter em mente a importncia do
versionamento da API.

Formato da representao
Para representarmos um recurso, podemos utilizar diversos formatos. Porm, dois deles
se sobressaem e so mais conhecidos e usados: XML e JSON. O primeiro usado na
representao de recursos e transporte de dados h bastante tempo, tanto por web
services SOAP, como REST, alm de outras aplicaes. J o JSON um formato um
pouco mais recente e que vem tomando o espao do XML devido a diversos fatores.

O poder do XML de representar dados indiscutvel, tendo inclusive um poder maior do


que o JSON e outros formatos. Porm, se compararmos o tamanho de um recurso

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 18/38
11/3/2014 Construindo uma RESTful API Parte 1

representado atravs de XML com o mesmo representado atravs de JSON, veremos


uma grande diferena. Por ser mais simples, o JSON ocupa um espao muito menor e
isso interfere bastante na quantidade de banda necessria na transferncia dos dados.

Isso acontece porque, junto com os dados, o XML tambm carrega muito texto
descartvel que apenas usado para manter sua estrutura. Enquanto isso, o JSON
carrega pouqussimo texto alm dos dados necessrios.

Outro ponto forte do JSON sua integrao com JavaScript, o que facilita o
desenvolvimento de aplicaes com HTML5. Afinal, JSON significa JavaScript Object
Notation e basicamente uma representao textual de um objeto no JavaScript. Por
isso, sua representao muito mais compatvel com a representao de objetos da
maioria das linguagens, diferente do XML.

Para melhor visualizarmos a diferena de simplicidade e tamanho entre os dois, podemos


visualizar as Listagens 5 e 6. Cada uma delas mostra o mesmo recurso representado
atravs de XML e JSON, respectivamente.

Listagem 5. Representao de um cliente utilizando XML.

<?xml version="1.0"?>
<cliente>
<nome>Fernando Camargo</nome>
<cpf>62854828532</cpf>
<idade>22<idade>
<telefones>
<telefone>6298350912</telefone>
<telefone>6232903845</telefone>
</telefones>
<email>fernando.camargo.ti@gmail.com</email>
<endereco>
<logradouro>Rua 12-A</logradouro>
<cep>63905192</cep>
<bairro>Setor Aeroporto</bairro>
<numero>168</numero>
<complemento>Apartamento 301</complemento>
<cidade>Goinia</cidade>
<estado>GO</estado>
<pais>Brasil</pais>
</endereco>
</cliente>

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 19/38
11/3/2014 Construindo uma RESTful API Parte 1

Listagem 6. Representao de um cliente utilizando JSON.

{
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",
"endereco": {
"logradouro": "Rua 12-A",
"cep": "63905192",
"bairro": "Setor Aeroporto",
"numero": 168,
"complemento": "Apartamento 301",
"cidade": "Goinia",
"estado": "GO",
"pais": "Brasil"
}
}

Observando as duas listagens, notamos que mais fcil de ler e de escrever a


representao no formato JSON. Tambm observamos que o XML possui muitas
repeties devido abertura e fechamento de cada tag. Alm disso, uma lista de valores,
como o caso do telefone neste exemplo, acaba desperdiando ainda mais texto,
precisando da repetio da tag <telefone>.

Ainda podemos notar que os objetos so expressos de forma muito mais natural atravs
de JSON. Isso tudo devido simplicidade desse formato e pelo fato de ter sido criado a
partir da notao de objetos do JavaScript.

Para verificarmos a diferena de tamanho, podemos remover todos os espaos


desnecessrios do texto e conferir o tamanho final de cada um dos arquivos. Ao
fazermos isso com o exemplo do cliente, obtemos 466 bytes com o XML e 314 bytes
com o JSON.

A diferena pode parecer pequena devido ao tamanho do objeto, mas se transferirmos


uma representao com uma lista de clientes, veremos uma diferena muito maior. Para
exemplificar, podemos criar uma lista de dez clientes utilizando esse mesmo cliente em
cada uma das representaes. Nesse simples caso, j atingimos 4,4KB com XML e 3,1KB

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 20/38
11/3/2014 Construindo uma RESTful API Parte 1

com JSON.

Se considerarmos que nosso cliente uma aplicao mvel com uma internet limitada e
um hardware no to potente, o uso de JSON causa uma grande diferena na quantidade
de dados transferida e no tempo de interpretao dos dados. Quando lidamos com esse
tipo de aplicao, qualquer reduo de gasto na banda da internet bem vinda.

Apesar de toda essa vantagem do JSON, ainda comum que vrias APIs deem a opo
aos desenvolvedores para escolher qual representao ele quer usar. Muito disso vem da
tradio do uso de XML e do costume de utiliz-lo. Porm, por outro lado, o Twitter e
outros grandes donos de APIs deixaram de dar suporte ao XML e passaram a suportar
somente o JSON como formato de representao. Ao projetarmos uma API, devemos
decidir se vamos adotar apenas um desses dois ou se vamos suportar os dois. A
princpio, recomendada a utilizao de JSON pelos motivos j discutidos.

Ainda nesse tpico, comum que alguns desenvolvedores representem os campos no


JSON utilizando a notao de nome de variveis comum em sua linguagem. Alguns usam
nomes separados com underline, como primeiro_nome, e outros usam o camelCase,
como primeiroNome. Para manter a conformidade com o JavaScript, recomendado o
uso do camelCase, independente da linguagem de preferncia do desenvolvedor.

Um ltimo assunto importante no tpico de formato quanto formatao de datas e


horrios. Em uma API REST usada por todo o mundo, podem acontecer diversos
problemas devido ao uso de diferentes time zones pelo servidor e seus clientes. Para
evitar tais erros, recomendado utilizar o padro ISO 8601, que define que a time zone
seja sempre UTC e que sempre siga o formato yyyy-MM-dd'T'HH:mm:ss.SSS'Z', sendo
esse texto uma String que pode ser usada na API Java com a classe
SimpleDateFormat. Para exemplificar, observe essa data e hora: 2013-09-
26T21:24:39.521Z.

Seguindo esses padres, clientes ao redor de todo o mundo podero utilizar sua API de
forma fcil e evitando erros comuns.

Identificao e ligao entre recursos


O gerenciamento da identificao dos recursos e a ligao entre eles um dos detalhes
mais importantes em uma API REST. Nesse momento, devemos nos preocupar ao
mximo com o conceito de HATEOAS. Isso significa que os recursos sero localizados
por hyperlinks e provero os hyperlinks para recursos relacionados.

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 21/38
11/3/2014 Construindo uma RESTful API Parte 1

Portanto, o primeiro passo incluir um novo campo em todo e qualquer recurso: href.
Esse campo ser disponibilizado no lugar do campo de identificao. Ou seja, ao invs de
termos um campo ID na representao, teremos o campo href. Isso porque ele ter
como valor uma URL que unicamente localiza tal recurso. Assim, o cliente da API poder
gravar esse hyperlink para identificar o recurso e poder requisit-lo novamente mais
tarde.

A Listagem 7 mostra o exemplo do Cliente apresentado anteriormente com esse novo


campo. Deve-se prestar ateno no fato de no haver um campo de ID, mas esse pode
ser extrado da URL, se desejado pelo usurio da API.

Listagem 7. Exemplificando o uso do campo href.

{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",
"endereco": {
"href": https://api.javamagazine.com.br/enderecos/8502hgo,
"logradouro": "Rua 12-A",
"cep": "63905192",
"bairro": "Setor Aeroporto",
"numero": 168,
"complemento": "Apartamento 301",
"cidade": "Goinia",
"estado": "GO",
"pais": "Brasil"
}
}

Esse campo no importante apenas para a identificao do recurso, mas tambm para
fazer a ligao dos recursos relacionados. Pode-se reparar na Listagem 7 que o
endereo retornado tambm possui um href, o que nos permite fazer outros tipos de
requisio em cima do mesmo, caso queiramos modific-lo utilizando um PUT ou um
POST, por exemplo. Veremos no prximo tpico que podemos, em alguns momentos,
retornar apenas o href do recurso relacionado, ao invs de retorn-lo por completo.

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 22/38
11/3/2014 Construindo uma RESTful API Parte 1

Representao parcial e paginao


Este tpico muito importante para melhorar a performance dos clientes e do servidor.
Atravs de representaes parciais e paginao, podemos reduzir a quantidade de dados
trafegados pela rede, tornando menor a necessidade de banda para suprir os clientes e
tambm fazendo com que a requisio seja respondida com um atraso menor.

Comeamos falando sobre representaes parciais. Elas so feitas dando uma forma ao
cliente para especificar quais informaes ele quer sobre determinado recurso. Ou seja,
ele seleciona quais campos devero ser retornados na representao, ao invs de obter
sempre o recurso completo.

Isso importante porque nem sempre o cliente necessitar do recurso completo para
seus propsitos. Assim, deve-se prover uma forma do mesmo identificar quais campos
devero ser retornados pelo servidor em requisies de GET.

Para essa e outras opes, comum utilizarmos a query-string da requisio GET para
se passar os parmetros necessrios. Assim, teremos no final da URL requisitada os
parmetros na forma j conhecida de query-string: <URL>?
parametro1=valor1metro2=valor2. Utilizando essa abordagem, podemos receber
um parmetro chamado fields, onde ser recebida a lista de campos desejados do
recurso.

Para exemplificar o uso do parmetro fields, consideremos o recurso Cliente apresentado


anteriormente e que um dos usurios da API deseja obter apenas o nome, CPF e e-mail
do cliente. A Listagem 8 mostra a requisio feita e a resposta em JSON.

Listagem 8. Representao parcial atravs do parmetro fields.

GET https://api.javamagazine.com.br/clientes/2g41s?fields=nome,cpf,email
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"email": "fernando.camargo.ti@gmail.com"
}

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 23/38
11/3/2014 Construindo uma RESTful API Parte 1

Como podemos ver nessa listagem, o cliente consegue especificar os campos desejados
passando os nomes dos mesmos separados por vrgula, formando a seguinte sintaxe: ?
fields=<fields,>. Porm, no vimos ainda como especificar os campos de recursos
relacionados, como o caso do endereo no nosso exemplo.

Nesse caso, adicionamos o campo do recurso relacionado acompanhado de parnteses,


dentro dos quais listamos os campos internos desejados. Podemos ver um exemplo
disso na Listagem 9, que mostra a requisio para os mesmos campos da Listagem 8,
com a adio da cidade, o estado e o pas do endereo do cliente.

Listagem 9. Representao parcial com recurso relacionado.

GET https://api.javamagazine.com.br/clientes/2g41s?fields=nome,cpf,email,endereco(
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"email": "fernando.camargo.ti@gmail.com",
"endereco": {
"href": https://api.javamagazine.com.br/enderecos/8502hgo,
"cidade": "Goinia",
"estado": "GO",
"pais": "Brasil"
}
}

Se no especificarmos os campos desejados de um recurso relacionado, devemos seguir


uma abordagem relacionada ao tpico anterior, sobre a ligao de recursos. Na verdade,
essa abordagem deve ser seguida mesmo quando o cliente no especificar os campos
desejados do recurso requisitado, ou seja, quando pedir a representao completa. Ela
consiste em retornar, por padro, o recurso relacionado incompleto, contendo apenas
seu href, como mostrado nas Listagens 10 e 11.

Listagem 10. Exemplo de recurso incompleto quando especificados apenas os campos


do recurso principal.

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 24/38
11/3/2014 Construindo uma RESTful API Parte 1

GET https://api.javamagazine.com.br/clientes/2g41s?fields=nome,cpf,email,endereco
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"email": "fernando.camargo.ti@gmail.com",
"endereco": {
"href": https://api.javamagazine.com.br/enderecos/8502hgo
}
}

Listagem 11. Exemplo de recurso incompleto quando no h especificao de campos


desejados.

GET https://api.javamagazine.com.br/clientes/2g41s
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",
"endereco": {
"href": https://api.javamagazine.com.br/enderecos/8502hgo
}
}

Com isso, estamos seguindo o princpio do HATEOAS e retornando uma resposta mais
curta por padro. Porm, deve-se dar a opo ao usurio de expandir a representao
do recurso relacionado, caso ele deseje obt-lo na mesma requisio.

Para adicionar essa opo, utilizamos o parmetro expand na query-string. Ele


funcionar da mesma forma que o parmetro fields, sendo que a representao final ter
os campos listados expandidos. Sua utilizao mostrada na Listagem 12.

Listagem 12. Uso do parmetro expand.

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 25/38
11/3/2014 Construindo uma RESTful API Parte 1

GET https://api.javamagazine.com.br/clientes/2g41s?expand=endereco
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",
"endereco": {
"href": https://api.javamagazine.com.br/enderecos/8502hgo,
"logradouro": "Rua 12-A",
"cep": "63905192",
"bairro": "Setor Aeroporto",
"numero": 168,
"complemento": "Apartamento 301",
"cidade": "Goinia",
"estado": "GO",
"pais": "Brasil"
}
}

A utilizao desse parmetro de expanso da representao no deve ser feita apenas


com recursos que se relacionem de um para um. Poderamos ter, por exemplo, uma
coleo de endereos. Essa coleo deveria vir apenas com os hyperlinks por padro,
dando a possibilidade de expanso atravs desse parmetro. A Listagem 13 exemplifica
a resposta padro para esse caso e a Listagem 14 exemplifica a resposta com os
endereos expandidos.

Listagem 13. Resposta padro para uma coleo de recursos relacionados.

GET https://api.javamagazine.com.br/clientes/2g41s
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 26/38
11/3/2014 Construindo uma RESTful API Parte 1

"enderecos": [{
"href": https://api.javamagazine.com.br/enderecos/8502hgo
},{
"href": https://api.javamagazine.com.br/enderecos/7hf852
}]
}

Listagem 14. Resposta com expanso dos endereos.

GET https://api.javamagazine.com.br/clientes/2g41s?expand=enderecos
Resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",
"enderecos": [{
"href": https://api.javamagazine.com.br/enderecos/8502hgo,
"logradouro": "Rua 12-A",
"cep": "63905192",
"bairro": "Setor Aeroporto",
"numero": 168,
"complemento": "Apartamento 301",
"cidade": "Goinia",
"estado": "GO",
"pais": "Brasil"
},{
"href": https://api.javamagazine.com.br/enderecos/7hf852,
"logradouro": "Rua 17-A",
"cep": "740705420",
"bairro": "Setor Central",
"numero": 68,
"complemento": "",
"cidade": "Goinia",
"estado": "GO",
"pais": "Brasil"
}]
}

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 27/38
11/3/2014 Construindo uma RESTful API Parte 1

Alm disso, podemos ter esse tipo de resposta com apenas hyperlinks como padro
tambm para requisies por determinada coleo de recursos. Esse o caso de um GET
na URL raiz de um recurso, que j foi visto anteriormente retornando os recursos
expandidos. Poderamos, por exemplo, requisitar diretamente a lista de endereos e o
servidor responderia com a lista de hyperlinks ou os endereos completos caso o cliente
requisite a expanso.

Como podemos ver, a combinao dos parmetros fields e expand traz grande
flexibilidade para o cliente, enquanto permitem uma otimizao no tamanho dos dados
retornados, de forma que o usurio da API obter apenas o necessrio para sua
aplicao. Porm, ainda falta um tpico importante nesse sentido. Ele diz respeito
paginao das respostas.

Imagine uma requisio de listagem dos produtos de um sistema. Se esse sistema tiver
milhares de produtos, a resposta ser gigantesca e possivelmente desnecessria.
Portanto, precisamos de uma forma de paginar por esses resultados. Para resolver isso,
poderamos requisitar os dez primeiros e, quando necessrio, requisitar os prximos dez
e assim por diante.

Ento, a API deve estar preparada para receber parmetros que definem quais itens o
cliente deseja. Tal opo pode ser disponibilizada de duas formas: atravs de parmetros
que indiquem o index inicial e o final, ou atravs de parmetros que indiquem o index
inicial e a quantidade de itens.

Na maioria dos casos, para tornar mais fcil para o cliente, a segunda abordagem
escolhida. Assim, um parmetro, que indicaria a quantidade de itens, fixada, e o cliente
varia apenas o parmetro do index inicial para paginar. Os nomes comumente adotados
so: offset e limit, sendo que offset define o deslocamento do item inicial, ou seja,
qual seria o index do primeiro item a ser retornado, enquanto limit define a quantidade
limite a ser retornada.

Com o exemplo em que obteramos os itens de dez em dez, poderamos fazer a primeira
requisio com o offset setado para 0, ou seja, a partir do primeiro item, e limitar a
quantidade de itens retornados a 10, atravs do parmetro limit. A prxima requisio
manteria o valor do limit e aumentaria para 10 o valor do offset. Assim, medida que
fosse necessrio, faramos novas requisies somando o valor do offset com o valor
utilizado no limite, obtendo todos os itens aos poucos, caso necessrio.

Entretanto, qual deve ser o comportamento da API quando seu usurio no passar
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 28/38
11/3/2014 Construindo uma RESTful API Parte 1

esses dois parmetros? Ela dever possuir valores padres para cada um deles e adot-
los quando algum desses parmetros no for passado pelo cliente. Normalmente, adota-
se o valor padro do offset como 0 e o valor do limit varia entre 10 e 25, dependendo
da deciso do desenvolvedor da API.

Porm, ainda temos mais um requisito: seguir o que definido pelo HATEOAS. Ou seja,
devemos garantir que nossa API retorne hyperlinks para a prxima pgina, pgina
anterior, primeira e ltima pgina, alm de alguns metadados, como o offset e o limit
utilizado, caso o usurio no tenha passado esses parmetros, e outros metadados
teis. Na Listagem 15 vemos uma requisio sem os parmetros de paginao
acompanhada de seu resultado e na Listagem 16 vemos a requisio seguinte que
utilizar o hyperlink recebido no campo next da resposta anterior.

Listagem 15. Exemplo de resultado paginado para requisio comum.

GET https://api.javamagazine.com.br/clientes
Resposta:
{
"href": "https://api.javamagazine.com.br/clientes",
"offset": 0,
"limit": 10,
"first": {"href": "https://api.javamagazine.com.br/clientes?offset=0"},
"previous": null,
"next": {"href": "https://api.javamagazine.com.br/clientes?offset=10"},
"last": {"href": "https://api.javamagazine.com.br/clientes?offset=990"},
"items": [
{"href": "https://api.javamagazine.com.br/clientes/61h58s"},
{"href": "https://api.javamagazine.com.br/clientes/f72baf"},
{"href": "https://api.javamagazine.com.br/clientes/823huf"},
{"href": "https://api.javamagazine.com.br/clientes/u23hf6"},
{"href": "https://api.javamagazine.com.br/clientes/fqgy2f"},
{"href": "https://api.javamagazine.com.br/clientes/vuhq9df"},
{"href": "https://api.javamagazine.com.br/clientes/vg782qw"},
{"href": "https://api.javamagazine.com.br/clientes/v90aqga"},
{"href": "https://api.javamagazine.com.br/clientes/vihaqgt9"},
{"href": "https://api.javamagazine.com.br/clientes/v7qafld"}
]
}

Listagem 16. Exemplo de resultado paginado utilizando hyperlink do campo next da

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 29/38
11/3/2014 Construindo uma RESTful API Parte 1

requisio anterior.

ET https://api.javamagazine.com.br/clientes?offset=10
Resposta:
{
"href": "https://api.javamagazine.com.br/clientes",
"offset": 10,
"limit": 10,
"first": {"href": "https://api.javamagazine.com.br/clientes?offset=0"},
"previous": null,
"next": {"href": "https://api.javamagazine.com.br/clientes?offset=20"},
"last": {"href": "https://api.javamagazine.com.br/clientes?offset=990"},
"items": [
{"href": "https://api.javamagazine.com.br/clientes/72r286"},
{"href": "https://api.javamagazine.com.br/clientes/7ncau2"},
{"href": "https://api.javamagazine.com.br/clientes/v3q9fu"},
{"href": "https://api.javamagazine.com.br/clientes/03nfi8a"},
{"href": "https://api.javamagazine.com.br/clientes/vin3w9"},
{"href": "https://api.javamagazine.com.br/clientes/v90wkas"},
{"href": "https://api.javamagazine.com.br/clientes/g30qgl9"},
{"href": "https://api.javamagazine.com.br/clientes/fuhqknag"},
{"href": "https://api.javamagazine.com.br/clientes/0pwnanjz"},
{"href": "https://api.javamagazine.com.br/clientes/b02ksdfj"}
]
}

Deve-se reparar nessas listagens que os hyperlinks retornados na resposta no


possuem o parmetro limit devido ao fato de estar usando o limite padro de 10. Se,
na primeira requisio, o cliente especificasse o limite a ser utilizado, esses hyperlinks
deveriam ser calculados utilizando-se esse limite. Tambm importante notar que livre
ao desenvolvedor retornar mais metadados, como a quantidade total de itens, por
exemplo.

Essa abordagem nos traz timos resultados. O primeiro deles reduzir a quantidade de
dados trafegados pela rede de uma s vez, fazendo com que o cliente seja mais
responsivo a seus usurios.

Alm disso, os hyperlinks retornados trazem a possibilidade de criao de


implementaes mais inteligentes do lado do cliente. Estes poderiam utilizar essas URLs
retornadas para fazer a paginao, ao invs de ficar construindo as prximas URLs

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 30/38
11/3/2014 Construindo uma RESTful API Parte 1

necessrias.

Como podemos ver at agora, deve-se manter duas coisas principais em mente ao
projetar uma API: HATEOAS e tentar reduzir ao mximo o tamanho das respostas, de
forma que elas retornem apenas o necessrio ao cliente e que no atrasem muito a
comunicao. Contudo, alm disso, ainda so necessrias algumas outras prticas para
criar uma boa API e continuaremos abordando-as a seguir.

Respostas de erro
Muitos fatores podem causar um erro na utilizao de uma API. Entre eles, esto erros
de validao de um recurso submetido, requisio inconsistente enviada pelo cliente,
conflito de informaes, alm de vrios outros. Alguns deles podem ser causados pela
m utilizao da API, enquanto outros podem ser erros comuns que a aplicao cliente
dever estar preparada para tratar, como erros de validao.

Em ambos os casos, a API deve retornar respostas de erro consistentes, que permitam
um tratamento para a aplicao cliente e ao mesmo tempo contenham uma explicao
direcionada ao desenvolvedor.

Com esses requisitos, faz-se importante as seguintes informaes em uma resposta de


erro: Status HTTP que descreva o que aconteceu de errado, um cdigo que identifique
unicamente o erro, informaes pertinentes a esse erro, uma mensagem que poder ser
mostrada ao usurio da aplicao cliente (caso desejado), uma mensagem mais
explicativa destinada ao desenvolvedor da aplicao cliente e uma URL que aponte para a
documentao desse erro.

Para se obter tanta informao, necessrio comear catalogando os possveis erros que
podero acontecer na API. Esse catlogo de erros dever possuir erros identificados por
um cdigo e estar presente na documentao da API. Atravs dessa documentao, o
desenvolvedor da aplicao cliente entender quais erros devero ser tratados e
preparar sua aplicao para utilizar os cdigos de erro na identificao e tratamento dos
mesmos.

Para exemplificar, veremos na Listagem 17 o resultado de uma requisio que tenta


cadastrar um cliente. Nesse caso, a aplicao cliente submeter um cliente cujo CPF j foi
cadastrado anteriormente, ento acontecer um erro de validao por conflito de CPFs.

Listagem 17. Exemplo de erro retornado no cadastro de um cliente cujo CPF j se

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 31/38
11/3/2014 Construindo uma RESTful API Parte 1

encontra cadastrado no sistema.

POST https://api.javamagazine.com.br/clientes
Resposta:
409 Conflict
{
"status": 409,
"code": 145,
"property": "cpf",
"message": "Um cliente com CPF '43819274830' j existe.",
"developerMessage": "Um cliente com CPF '43819274830' j existe. Verifique se e
"moreInfo": "https://developers.javamagazine.com.br/docs/api/errors/145"
}

Nessa listagem, estamos considerando que o cdigo 145 localiza unicamente o erro de
conflito entre campos que devem possuir valores nicos no sistema. Para que esse tipo
de erro seja tratado, importante retornarmos qual o campo em que tal erro aconteceu.
No cliente, por exemplo, poderamos ter um conflito entre os campos nicos de CPF e e-
mail. Tambm podemos observar que existem duas mensagens.

Uma destinada ao usurio comum, que poder ser exibida pela aplicao cliente (se
desejado) e uma destinada ao desenvolvedor, que tenta explicar uma possvel causa do
erro. Alm disso, retornada a URL que localiza a documentao desse erro, onde
possvel encontrar mais detalhes sobre o mesmo.

O ponto mais importante aqui o cdigo que localiza o erro. Sem ele, um sistema no
poder fazer nenhum tratamento especial para o erro que aconteceu. Portanto, muito
importante catalogar cada um dos erros possveis na API para trazer uma boa
experincia aos desenvolvedores das aplicaes clientes da mesma, ajudando-os a
satisfazer os usurios finais.

Segurana
Quando falamos da segurana de uma API, temos que ter algumas coisas em mente. A
primeira delas que, por se tratar de REST, a API stateless. Isso significa que o
usurio dever ser autenticado em cada requisio para que seja verificado se o mesmo
possui autorizao para acessar determinado recurso. Com isso, o envio de login e senha
em cada requisio se torna claramente uma pssima opo.
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 32/38
11/3/2014 Construindo uma RESTful API Parte 1

Para contornar isso, o usurio passar por um login seguro atravs de nosso servio, ao
invs de submeter o login e senha ao cliente. Depois disso, nosso servio o redireciona
para a aplicao cliente disponibilizando uma chave para a mesma. Com a posse dessa
chave, a aplicao autenticar o usurio em cada requisio futura.

Existem vrias vantagens para essa abordagem. Uma delas a exposio limitada. Para
entend-la, imagine que um usurio de nosso site utiliza uma aplicao cliente de nossa
API. Quando a aplicao redirecionar o usurio para que ele seja autenticado em nosso
site, essa aplicao obter a chave a ser utilizada para agir como determinado usurio.

Por no expormos o login e a senha do usurio para essa aplicao, visto que o usurio
se autenticar atravs do site ou alguma forma de biblioteca (SDK) disponibilizado por
nosso servio, podemos limitar o acesso dessa aplicao.

Assim, poderamos deixar a cargo do usurio decidir quais permisses tal aplicao
possui sobre seus dados, sendo que as permisses seriam pedidas no momento do
login.

Um exemplo clssico disso o Facebook. Comumente, vrias aplicaes o utilizam como


uma forma de autenticao e tambm para poder publicar em nome dos usurios.
Quando o usurio tenta acessar pela primeira vez tais aplicaes, elas o redirecionam
para uma pgina de login e autorizao do Facebook.

Nela, o usurio verifica quais permisses a aplicao est pedindo para acessar de sua
conta e autoriza o acesso. A partir da, a aplicao obtm uma chave que ser utilizada
quando for acessar a API do Facebook em nome do usurio.

Outra vantagem dessa abordagem a rastreabilidade. Como as aplicaes tero que


utilizar essa chave, a qual criada para cada uma, pode-se rastrear as aes de cada
aplicao cliente em nome de determinado usurio. Isso pode ser importante para o caso
delas estarem utilizando indevidamente o acesso obtido em nome do usurio.

Tambm muito til no caso de uma alterao da senha do usurio. Nesse caso, se a
aplicao cliente dependesse do login e da senha, ela perderia o acesso quando o usurio
alterasse sua senha. Isso no acontece com o uso de uma chave para cada aplicao
cliente.

Com todas essas vantagens, a escolha natural na autenticao o uso de uma chave
passada para o cliente. Mas que caminho podemos seguir na implementao de tal
funcionalidade? Para isso, existem diversos padres de segurana conhecidos. Portanto,
http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 33/38
11/3/2014 Construindo uma RESTful API Parte 1

ao invs de criarmos um novo esquema de segurana, devemos seguir um desses


padres.

O padro mais conhecido e mais utilizado pelas APIs de grandes empresas o OAuth.
Atualmente, ele est na verso 2.0, mas ainda existem grandes APIs utilizando sua
verso 1.0a. Por se tratar de um padro, geralmente temos que entend-lo e
implement-lo. Porm, existem algumas bibliotecas que ajudam na implementao,
apesar de no tirar a necessidade do entendimento do mesmo.

Por ser muito extenso, o estudo sobre OAuth ser deixado para outro momento. Antes
de finalizar o tpico de segurana, no entanto, precisamos nos atentar a mais um
detalhe: a autorizao no deve ser baseada em URLs, mas sim em recursos.

Isso bem simples de se entender, afinal, a API construda a partir de recursos. Ento,
por mais que seja tentador simplificar o esquema de autorizao atravs de URLs para
simplificar a implementao, deve-se faz-lo sobre recursos, para se evitar falhas de
segurana.

Cache atravs de ETag


Para possibilitarmos o cache por parte da aplicao cliente, podemos adotar um esquema
que utiliza o header HTTP ETag. Tal implementao feita de forma que, quando a
aplicao cliente requisitar determinado recurso pela primeira vez, o servidor dever
retornar esse header com um valor que identifique o estado atual do recurso. Em uma
requisio posterior, o cliente passar esse valor de volta ao servidor, como uma forma
de avisar que j possui o recurso em cache naquele estado. Assim, se no houver
mudanas no estado do recurso, o servidor apenas avisa o cliente de que poder
continuar usando tal verso do recurso. Caso contrrio, o servidor responde com a nova
verso e um novo valor no ETag.

Para deixar mais claro, podemos imaginar que haja um controle de verso no servidor, de
tal forma que a cada modificao de um recurso, o valor da verso incrementado.
Assim, pode-se utilizar esse valor da verso para se criar um conjunto de caracteres que
representem o estado atual do recurso.

No caso de uma requisio por mltiplos recursos, podemos combinar as verses dos
mesmos para gerar o conjunto de caracteres passado na ETag.

A Listagem 18 mostra como um recurso do tipo Cliente retornado como resposta para

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 34/38
11/3/2014 Construindo uma RESTful API Parte 1

uma requisio, em conjunto com sua ETag. Enquanto isso, a Listagem 19 mostra a
prxima requisio da aplicao cliente, a qual j possui em cache a verso retornada
anteriormente e envia ao servidor o valor que representa tal verso.

Nessa listagem, ainda no houve uma atualizao do recurso, ento o servidor responde
com o status 304 Not Modified. J na Listagem 20, em uma nova requisio, o recurso
j foi modificado, ento o servidor retorna a representao dele em conjunto com a nova
ETag.

Listagem 18. Requisio inicial por um Cliente em conjunto com a resposta do servidor.

GET https://api.javamagazine.com.br/clientes/2g41s
Headers da resposta:
ETag: 62wsc482nsadf742f7831
Corpo da resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 22,
"telefones": ["6298350912", "6232903845"],
"email": "fernando.camargo.ti@gmail.com",
"enderecos": [{
"href": https://api.javamagazine.com.br/enderecos/8502hgo
},{
"href": https://api.javamagazine.com.br/enderecos/7hf852
}]
}

Listagem 19. Requisio posterior, no momento em que a aplicao cliente possui a


verso atual em cache.

GET https://api.javamagazine.com.br/clientes/2g41s
Headers da requisio:
If-None-Match: 62wsc482nsadf742f7831
Resposta:
304 Not Modified

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 35/38
11/3/2014 Construindo uma RESTful API Parte 1

Listagem 20. Nova requisio depois de o recurso ter sido modificado.

GET https://api.javamagazine.com.br/clientes/2g41s
Headers da requisio:
If-None-Match: 62wsc482nsadf742f7831
Headers da resposta:
ETag: 2tfh892fds982nksaf8932
Corpo da resposta:
{
"href": https://api.javamagazine.com.br/clientes/2g41s,
"nome": "Fernando Camargo",
"cpf": "62854828532",
"idade": 23,
"telefones": ["6298350912"],
"email": "fernando.camargo.ti@gmail.com",
"enderecos": [{
"href": https://api.javamagazine.com.br/enderecos/8502hgo
},{
"href": https://api.javamagazine.com.br/enderecos/7hf852
}]
}

Nessas listagens, podemos perceber a interao da aplicao cliente com o servidor.


Nessa interao, verificamos trs pontos importantes: o uso do header ETag na resposta
do servidor, o uso do header If-None-Match na requisio do cliente e o status 304 Not
Modified retornado pelo servidor. Em cima desses trs pontos, podemos construir uma
boa soluo que permite a utilizao de cache pela aplicao cliente.

A grande vantagem disso o baixo consumo da rede. Pelo fato do servidor responder
com um simples status HTTP, bastante rede poupada e a requisio se torna mais
rpida. Com essa abordagem, tambm possvel que a aplicao cliente apresente o
recurso em cache e verifique por atualizaes em plano de fundo. Enfim, essa uma
funcionalidade muito importante que pode ser feita de uma maneira fcil. Portanto, no
h porque no faz-la.

Concluso
Nesta primeira parte do artigo, vimos os conceitos bsicos do estilo arquitetural que vem
ganhando espao na implementao de web services. Tambm foram mostradas as
principais diferenas entre um web service REST e um SOAP, destacando as vantagens

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 36/38
11/3/2014 Construindo uma RESTful API Parte 1

do REST para a criao de uma API destinada a aplicaes clientes mantidas por
terceiros.

Depois desse aprendizado sobre as regras do REST e a justificativa de porque utiliz-lo,


vimos as principais boas prticas que devemos seguir para implementarmos uma boa
RESTful API. Atravs dessas boas prticas, podemos criar uma API que no s trar
grande produtividade aos desenvolvedores das aplicaes clientes, mas tambm lhes
trar grande flexibilidade, alm de melhorar o desempenho do servidor e ter sua
manuteno facilitada.

Na segunda parte, ser mostrado os conceitos por trs do OAuth 2.0 e tambm um
exemplo utilizando as boas prticas atravs da especificao JAX-RS em conjunto com a
implementao Apache CXF, que j possui suporte criao da autenticao com o
padro OAuth 2.0.

Links

SOAP vs REST para aplicaes mobile.


blogs.captechconsulting.com/blog/jack-cox/soap-vs-rest-mobile-services

Informaes sobre REST.


www.restapitutorial.com

Artigo sobre o versionamento de APIs.


barelyenough.org/blog/2008/05/versioning-rest-web-services

Artigo que cita exemplos de APIs que usam versionamento via URL e via
Accept header.
www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned

Fernando Camargo

Fernando Camargo desenvolvedor Java EE, Android e Grails. Atualmente, graduando em Engenharia de
Computao na UFG e desenvolvedor na Fibonacci Solues geis. Desenvolve em Java desde comeo de
2009 e para Android desde come [...]

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 37/38
11/3/2014 Construindo uma RESTful API Parte 1

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=29904 38/38

Anda mungkin juga menyukai