Programação para Web I

Aula 11 : Introdução ao HTTP/REST

Aula 11 - Introdução ao HTTP/REST

Exemplos de aula

HTTP

Protocolo HTTP
Estrutura do protocolo HTTPModelo de requisição do HTTP
  • Modelo requisição/resposta
Sobre API

Uma das principais necessidades da computação é o uso de linguagens e padrões consistentes para que diferentes máquinas e aplicações possam interagir de maneira confiável. É muito comum atualmente que aplicações utilizem de interfaces para acessar todo o tipo de dados (desde dados de um usuário até vídeos no youtube, por exemplo). É daí que surge as Application Programming Interface, ou as APIs.

Arquitetura 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
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" }

REST com FetchAPI

Fetch GET
js Fetch GET
const url = 'http://meusite.com/api/'
var requisicao = fetch(url)
var dado = requisicao.then(function(resposta){
    return resposta.json()
})

dado.then(function(dado){
    console.log(dado)
})

A sintaxe acima realiza uma requisição no endpoint http://meusite.com/api. Enquanto aguardamos a resposta, o servidor da url indicada recebe a requisição, processa e envia de volta para o nosso script os dados solicitados. Neste caso, utilizamos a função json()para tratar os dados que esperamos receber com a codificação JSON.

Repare que ao realizar uma requisição do tipo GET, não há necessidade de enviar mais nenhum dado além da url, pois a finalidade desse método é apenas obter os dados de um serviço.

Fetch POST
js Fetch POST
const url = 'http://meusite.com/api/'
var opcoes = {
    method: 'POST',
    body: JSON.stringfy(meus_dados),
    headers: {
        'content-type': 'application/json'
    }
}
var requisicao = fetch(url, opcoes)
var dado = requisicao.then(function(resposta){
    console.log(resposta.status)
    return resposta.json()
})

dado.then(function(dado){
    console.log(dado)
})

Quando o objetivo é enviar dados ao servidor é necessário realizar algumas especificações. Vamos informar, além do método que desejamos utilizar, os dados que queremos enviar e também qual o tipo de conteúdo estamos enviado. Isso é importante para que o servidor possa reconhecer facilmente e tratar os dados recebidos.

É importante lembrar que a resposta do serviço pode variar de acordo com a forma que o mesmo foi implementado. É comum que o cabeçalho da resposta retorne o próprio objeto enviado em caso de sucesso. Além disso, um serviço que implementa corretamente as restrições do padrão REST também deve inserir no status da resposta enviada o estado, facilitando o tratamento de eventuais erros pelo cliente.

Fetch DELETE
js Fetch DELETE
var id = 50
var url = 'http://meusite.com/api/' + id
var opcoes = {
    method: 'DELETE',
}
var requisicao = fetch(url, opcoes)
var dado = requisicao.then(function(resposta){
    console.log(resposta.status)
    return resposta.json()
})

dado.then(function(dado){
    console.log(dado)
})

A ação de deletar também pode ser implementada através dos métodos usando o DELETE. Neste caso, é comum não haver dados no corpo da mensagem de uma requisição DELETE(apesar de não haver proibição), por isso também é comum especificar um identificador único para que o servidor saiba o que deve ser deletado.

O método DELETE é sempre destrutivo e deve ser tratado com cuidado. É comum que serviços REST implementem alguma forma de autenticação para evitar que usuários deletem recursos do qual não possuem acesso/autorização.

Fetch PUT
js Fetch PUT
const url = 'http://meusite.com/api/'
var requisicao = fetch(url)
var dado = requisicao.then(function(resposta){
    return resposta.json()
})

dado.then(function(dado){
    console.log(dado)
})

A sintaxe acima realiza uma requisição no endpoint http://meusite.com/api. Enquanto aguardamos a resposta, o servidor da url indicada recebe a requisição, processa e envia de volta para o nosso script os dados solicitados. Neste caso, utilizamos a função json()para tratar os dados que esperamos receber com a codificação JSON.

Repare que ao realizar uma requisição do tipo GET, não há necessidade de enviar mais nenhum dado além da url, pois a finalidade desse método é apenas obter os dados de um serviço.

Outros tópicos

Insomnia
Insominia Logo

O Insomnia é um cliente para APIs open source capaz de gerar, organizar e documentar requisições REST, SOAP, GraphQL e GRPC.

Esta ferramenta é extramemente útil para realizar os testes de requisições para uma API sem a necessidade de gerar um cliente com essa finalidade.

Site Insominia

Mão na Massa

Exercício: Frontend Usuários

Crie uma página HTML contendo um javascript que seja capaz de exibir todos os usuários de uma API e realizar novos cadastros. Isso deverá ser feito usando as seguintes especificações:

Endpoint

https://api-ppw.herokuapp.com/api/000000/users - Substitua 000000 pelo seu código de estudante

GET https://api-ppw.herokuapp.com/api/000000/users - Retorna a lista com todos os usuários. Lembre-se de que não é necessário passar nada no corpo/body da requisição

POST https://api-ppw.herokuapp.com/api/000000/users - Salva um novo usuário. Deve haver um corpo de mensagem como o especificado abaixo:

Modelo de Dado

{
    "name": String,
    "password": String
}

Lembre-se de substitui o String por um valor correspondente

Outras considerações

Utilize o insomnia ou outro software para testar as requisições. Outras informações também podem ser encontradas na documentação da API Fetch

O modelo também deverá ser estilizado com um CSS básico à escolha do estudante.