Java para Web

Aula 09 : REST

Aula 09 - REST

Exemplos de aula

REST

Arquitetura REST

A Web que conhecemos é recheada de recursos. Estes recursos podem ser entendidos como basicamente qualquer coisa que possa ser identificada e endereçada. Dessa forma, é muito comum atualmente que os dados que acessamos ao navegar pela Web possuam uma estrutura sólida que permita que diferentes serviços possam se comunicar usando um padrão comum.

Uma das arquiteturas mais utilizadas na web para criação de APIs que permitem a troca informações entre serviços é o padrão REST (Representational State Transfer). Essa arquitetura define um conjunto de restrições na representação e operação de dados que são utilizadas na criação de serviços web.

REST é um acrônimo para Representational StateTransfer.

Site com documentação para o REST

Princípios REST

A arquitetura REST segue 6 princípios:

  1. Cliente/Servidor - separa o armazenamento de dados da interface de usuário
  2. Stateless - toda requisição do cliente precisa conter toda informação necessária.
  3. Cacheable - As respostas à uma requisição podem conter informações sobre a reutilização de uma resposta
  4. Interface Uniforme - aplica o conceito de generalização de engenharia de software, padronizando o acesso aos dados da aplicação
  5. Sistema de Camadas - permite a composição hierarquica de acesso aos dados
  6. Código sob-demanda - permite a criação de clientes que podem requisitar informações e extende-las sem a necessidade de alterar a arquitetura do servidor.

URI REST

A abstração chave na arquitetura REST é o resource (recurso). Toda informação que pode ser nomeada pode ser um resource na implementação REST. Por exemplo:

  • Usuário
  • Foto
  • Time de Futebol
  • Jogador de Futebol
  • Pokémon
  • Treinador Pokémon

Uma resource pode ser identificado de maneira hierarquica. Dessa forma, nascem os identificadores chamados de URI (Unified Resource Identifier)

/usuarios
/usuarios/fotos
/time/jogador
/treinador
/treinador/pokemon/25
Boas Práticas REST

Por boa prática, utilizamos algumas regras para declarar resources:

Use substantivos para recursos e verbos para ações

Utilize nomes substantivos e verbos adequados para cada situação, colocando no substantivos no plural quando necessário

Document

Representa um objeto singular:

http://localhost/gerenciamento http://localhost/admin
Collection

Representa uma coleção de objetos gerenciada pelo servidor:

http://localhost/usuarios http://localhost/labs/07/computadores
Store

Representa uma coleção de objetos gerenciada pelo cliente:

http://localhost/usuario/200/carrinho http://localhost/usuario/200/playlist
Controller

Representa uma função adicional aplicada aos dados:

http://localhost/hotel/200/check-in http://localhost/temporada/01/start

Use barra para relações de hierarquia

Para representar relações de hierarquia de um recurso com outro (ex.: Usuário possui fotos), utilize a barra:

http://localhost/bancos/contas/400A

Não use barras no final de uma URI

A barra no final de uma URI não adiciona nenhum valor semântico ao endereço e pode causar confusão.

http://localhost/usuarios/ http://localhost/usuarios # Melhor

Use hífens (-) para aprimorar a leitura de uma URI

Utilize hífens para separar palavras quando possível, pois são mais fáceis de ler quando inseridos dentro de uma URI

http://localhost/carrosDeAluguel http://localhost/carros-de-aluguel # Melhor

Evite o uso de traço baixo (_)

O traço baixo (underline), pode ser facilmente confundido. Use hífens.

http://localhost/carros_de_aluguel http://localhost/carros-de-aluguel # Melhor

Evite o uso de letras maiúsculas

Procure ser consistente nos caracteres utilizados

http://localhost/Usuarios http://localhost/usuarios # Melhor

Não adicione a extensão requerida na URI da requisição

O HTTP já possui um cabeçalho para definir o tipo de dado requisitado chamadoContent-Type

http://localhost/usuarios.json http://localhost/usuarios # Melhor

Use Query String para filtrar coleções

As query strings são melhor utilizadas como filtros para a consulta a um determinado recurso

http://localhost/paises?continente=America http://localhost/paises?continente=Africa&limite=5

Nunca use o nome das funções CRUD na URI

O protocolo HTTP já possui verbos em seu protocolo para definir estes tipos de requisição (GET, POST, DELETE...)

http://localhost/usuarios/GET http://localhost/usuarios/Adicionar
Métodos HTTP REST

Para mapearmos a implementação de um CRUD (Create, Read,UUpdate, Delete) usando a arquitetura REST, iremos utilizar os métodos descritos pelo protocolo HTTP como referência. Para isso, usaremos:

  • GET, para consultar resources
  • POST, para adicionar resources
  • PUT, para atualizar resources
  • DELETE, para deletar resources

Adicionalmente, podemos utilizar:

  • PATCH, para atualizar partes de um resource
  • PUT, para adicionar resources

GET REST

O método GET tem a finalidade de retornar dados em nossa API. Podemos consultar um conjunto de dados (por exemplo, uma collection). Não é necessário passar nada no corpo da mensagem.

json GET
GET "/usuarios"

//RETORNO
[
    { "_id": 1, "login": "prezi", "senha": "abc123"},
    { "_id": 2, "login": "delta", "senha": "!@#$DFSER"},
    { "_id": 3, "login": "alfa", "senha": "USER123$"},
]

Ou um único recurso:

json GET
//REQUISIÇÃO
GET "/usuarios/3" // usuarios/:id

//RETORNO
{ "_id": 3, "login": "alfa", "senha": "USER123$"}
POST REST

O método POST pode ser utilizado para inserir novos objetos em uma coleção. É necessário passar no corpo da mensagem o objeto completo a ser inserido. O retorno pode ser o próprio objeto enviado.

json POST
//REQUISIÇÃO
POST /usuarios

//BODY
{ "login": "beta", "senha": "betinho123"}
PUT REST

O método PUT será utilizado para atualizar um recurso ou coleção. É necessário passar no corpo da mensagem um objeto completo a ser atualizado. O retorno, em caso de sucesso, pode ser o próprio objeto enviado.

json PUT
//REQUISIÇÃO
PUT /usuarios/3

//BODY
{ "login": "diddy", "senha": "QWERTY"}

Adicionalmente, o método PUT também pode ser utilizado para inserir novos objetos, dado que caso o usuário de id 3 não exista, ele será criado.

DELETE REST

O método DELETE é utilizado para deletar recursos. Não é necessário passar nada no corpo. O retorno pode ser, em caso de sucesso, o próprio objeto deletado.

json DELETE
//REQUSIÇÃO
DELETE /usuarios/5000
PATCH REST

O método PATCH é utilizado para realizar alterações em um recurso, geralmente em parte dele. O retorno geralmente é o recurso atualizado.

json DELETE
//REQUISIÇÃO
PATCH /usuarios/5000

//BODY
{ "senha": "CASACO1992" }

Aplicação Express

Recurso de Aplicação REST

Utilizando o objeto javascript abaixo, podemos realizar a implementação de um CRUD básico para ilustrar a arquitetura REST que entrega dados no formato JSON.

json personagens.json
var dados = {
    "personagens": [
        {
            "nome": "Willas",
            "raca": "humano",
            "idade": 43
        },
        {
            "nome": "Ernal",
            "raca": "elfo",
            "idade": 125
        },
        {
            "nome": "Villey",
            "raca": "humano",
            "idade": 27
        },
        {
            "nome": "Furi",
            "raca": "anão",
            "idade": 50
        },
    ]
}
GET Exemplo

Para consultar todos os personagens:

js personagens.js
// GET "/personagens"
router.get('/', function(req, res){
    res.json(dados.personagens)
})

Para consultar o personagem de nome ``Ernal``:

js personagens.js
// GET /personagens/1
router.get('/:id', function(req, res){
    res.json(dados.personagens[req.params.id])
})

Para consultar apenas personagens humanos:

js personagens.js
// GET "/personagens?raca=humano"
router.get('/', function(req, res){
    var filtered = dados.personagens.filter(function(element){
        return element.raca == req.query.raca
    })
})
POST Exemplo

Para adicionar um novo personagem:

js personagens.js
// POST "/personagens" BODY { "nome": "Eragon", "raca": "humano", "idade": 16}
router.post('/', function(req, res){
    var personagem = req.body
    dados.personagens.push(personagem)
    res.json(personagem)
})
PUT Exemplo

Para modificar um personagem:

js personagens.js
// PUT "/personagens/1" BODY { "raca": "humano", "idade": 16 }
router.put('/:id', function(req, res){
    var personagem = req.body
    if(dados.personagens[req.params.id]){
        dados.personagens[req.params.id] = personagem
    }
    res.json(dados.personagens[req.params.id])
})
DELETE Exemplo

Para deletar um personagem:

js personagens.js
// DELETE "/personagens/1"
router.delete('/:id', function(req, res){
    var deleted = dados.personagens.splice(req.params.id, 1)
    res.json(deleted)
})

Mão na Massa

Exercício: API Oficinas

Implemente uma API REST capaz de responder as solicitações de um CRUD para este conjunto de dados. Utilize um arquivo JSON para armazenar e manipular os dados da API. Crie rotas para cada um dos resources encontrados no arquivo JSON.