Back-End

15 jan, 2019

REST API com Node.js: back-end e front-end

Publicidade

Para começar este artigo vamos primeiro entender o que são APIs e qual a vantagem dessa abordagem em cima de um sistema único, onde temos tudo integrado.

Podemos pensar em APIs como uma ponte que liga duas ilhas, mas no caso de software, uma API pode ser usada por diversas áreas de negócio, não sendo necessário ao consumidor conhecer detalhes sobre sua implementação.

Elas são interfaces de integração que facilitam a troca de informações entre n aplicações, nos permitindo ter até mesmo várias caras para uma única aplicação – uma versão móvel, outra desktop e uma web.

Uma API pode ser acessada através de um endereço (minhaapi.com.br/api/v1/alunos) onde, ao acessarmos, teremos o seguinte retorno:

{
  "alunos":
    [
      {
        "nome": "Aluno1",
        "idade": 12
      },
      {
        "nome": "Aluno2",
        "idade": 13
      },
      {
        "nome": "Aluno3",
        "idade": 14
      },
      {
        "nome": "Aluno4",
        "idade": 15
      }
    ]
}

Com isso, temos uma representação de fácil entendimento de como seria uma API que retornaria uma lista de alunos e poderia ser usada em qualquer sistema que queira essa informação.

Dito isso, podemos avançar para o próximo conceito, que seria o REST. Podemos entender REST (Representational State Transfer) como a padronização da arquitetura web, uma abstração do protocolo HTTP, URL e os verbos HTTP.

Para ter uma API REST com um significado semântico onde olhamos certa URL e o verbo que é usado para a consumir, podemos entender quase de imediato qual comportamento esperar.

Temos quatro verbos principais e mais utilizados para realização de requisições, sendo eles: GET, POST, PUT, DELETE. Vamos ver como ficaria nossa API utilizando o REST:

  • GET minhaapi.com.br/api/v1/alunos (onde iremos recuperar uma lista de alunos)
  • POST minhaapi.com.br/api/v1/alunos — data {nome: Aluno5, idade: 16}
  • DELETE minhaapi.com.br/api/v1/alunos/1 (aqui passamos o id 1 do aluno cadastrado e ele será excluído)
  • PUT minhaapi.com.br/api/v1/alunos/1 — data {nome: Nome novo; idade: 20} (já aqui, passamos o id do aluno e mais as informações a serem atualizadas)

Agora que entendemos um pouco do padrão REST e como ele nos ajuda semanticamente a construir uma API melhor usando os verbos HTTP corretos para cada requisição, para refinar melhor as coisas precisamos conhecer o status code – e o que é isso ?

Toda requisição realizada para um servidor, sempre é retornado o status code na resposta. Ele é o indicador do que ocorreu com aquela requisição. Se deu certo, se a API falhou, se o servidor falhou ou se um determinado endereço existe. Recomendo o artigo da caelum para melhor entendimento sobre os padrões e princípios REST.

Entendemos, por alto, o que é uma API REST com os parágrafos anteriores.

Agora colocaremos isso em prática. Vamos construir uma API em node usando express, e para tornar o artigo mais didático, seguirei uma arquitetura simples. Vamos supor que sua máquina já está configurada com node e npm.

Nosso primeiro passo é criar um diretório para o projeto de API. Vou chamar esse diretório de alunos-api. Feito isso, vamos abrir o terminal (qualquer um) e navegar até nossa pasta recém criada.

Dentro da pasta vamos digitar:

npm init -y

Com esse comando criaremos um package.json que será a base de configuração da nossa aplicação e teremos o seguinte resultado:

Agora que temos nosso package.json configurado, podemos instalar algumas dependências. A primeira delas é o express. Para instalar, basta ir no terminal na pasta do projeto e digitar:

npm install express
express install

Para evitar dores de cabeça enquanto desenvolvemos e ter as alterações rodando ao modificarmos e salvarmos algum arquivo do projeto, podemos usar um pacote chamado nodemon. Para instalar, vamos usar o npm install, só que como esse pacote só será usado para o desenvolvimento, vamos usar a flag

— save-dev

npm install — save-dev nodemon

Agora que já temos esses dois pacotes essenciais, podemos configurar o script para rodar nossa aplicação em desenvolvimento. Antes, vamos abrir o projeto em um editor de texto preferido. No meu caso, o Visual Studio Code.

Agora vamos editar nosso package.json na propriedade de scripts. Vamos inserir uma outra propriedade chamada dev, ficando assim:

“scripts”: {
    “dev”: “nodemon src/app.js”,
    “test”: “echo \”Error: no test specified\” && exit 1"
}
package.json com scripts modificado

Esse script é chamado toda vez que executarmos o comando no terminal, dentro da pasta do projeto.

npm run dev

Acionando dessa forma, o nodemon que chama o app.js que ficará dentro da pasta src. Como boa prática vamos manter nossa base de código em uma pasta chamada src, que fica na raiz do nosso projeto, e dentro dela vamos criar nosso arquivo app.js.

Agora que temos a estrutura inicial da aplicação, vamos começar a escrever algumas coisas no nosso app.js e entender melhor como express funciona.

Para utilizar qualquer pacote em nossa aplicação node, temos que importar o pacote desejado. Podemos observar isso na primeira linha.

Na segunda linha estamos instanciando o express para podermos utilizar suas funções.

const express = require('express') //importacao do pacote
const app = express() //instanciando express
app.get('/', function (req, res) { //endereco da requisicao onde e retornado hello world
  res.send('Hello World')
})
app.listen(3000) //execucao do servidor

Na terceira linha temos a instância do express utilizando um método get, que aponta para determinada rota, onde ele recebe dois parâmetros, sendo o primeiro a rota, que neste caso é “/”, e o segundo parâmetro um callback que possui dois parâmetros (req, res), sendo o req utilizado para obter informações e são mandadas para esse url e res, utilizado para enviar uma resposta para quem está requisitando.

O comportamento seria o seguinte:

  • 1 – Cliente solicitou alguma coisa no endereço http://localhost:3000/
  • 2 – Servidor retorna, no caso do nosso exemplo, um html com texto “Hello World”

E a nossa última linha de código é onde iniciaremos, de fato, o servidor onde passamos como parâmetro a porta que será executada quando rodarmos o npm run dev. Depois de iniciar, podemos ir até o nosso navegador e acessar a url localhost:3000/, obtendo a resposta hello world.

Agora temos uma noção de como devolver uma página html com alguma informação usando a mesma função anterior. Podemos devolver um arquivo html ou um json, no caso de uma API.

Criaremos um array de objetos JavaScript contendo as informações que queremos devolver para quem está solicitando.

Nosso app.js ficará dessa forma:

const express = require('express') //importacao do pacote
const app = express() //instanciando express

const alunos = [
  {
    nome: 'Aluno1',
    idade: 12
  },
  {
    nome: 'Aluno2',
    idade: 13
  },
  {
    nome: 'Aluno3',
    idade: 14
  },
  {
    nome: 'Aluno4',
    idade: 15
  }
]

app.get('/', function (req, res) { //endereco da requisicao onde e retornado hello world
  res.send(alunos)
})

app.listen(3000) //execucao do servidor

Agora, ao acessarmos a URL da nossa API, vamos obter o seguinte retorno:

resposta da requisição. um array de objetos

Temos uma API funcionando, simulando uma consulta ao banco de dados onde é retornada uma lista de alunos. Agora é possível consumirmos isso de um navegador, do postman, de uma aplicação web e de um aplicativo.

Vamos só melhorar a URL da nossa aplicação para ficar mais semântica.

const express = require('express') //importacao do pacote
const app = express() //instanciando express

const alunos = [
  {
    nome: 'Aluno1',
    idade: 12
  },
  {
    nome: 'Aluno2',
    idade: 13
  },
  {
    nome: 'Aluno3',
    idade: 14
  },
  {
    nome: 'Aluno4',
    idade: 15
  }
]

app.get('/api/v1/alunos', function (req, res) { //endereco da requisicao onde e retornado hello world
  res.send(alunos)
})

app.listen(3000) //execucao do servidor

Pronto, nossa API está finalizada. Agora podemos consumir diretamente da nossa aplicação web.

Para começar a construção de nossa aplicação consumidora, criaremos uma pasta chamada alunos-front dentro da pasta alunos-api. Logo em seguida abriremos a pasta criada no editor de texto preferido. Já com o editor aberto criaremos um arquivo index.html com uma estrutura HTML5.

esqueleto de página html5

Marcaremos nosso html com um título para lista e a lista em si para visualizarmos como ficará o html. E para rodarmos a aplicação front, instalaremos um pacote muito bom para servir páginas estáticas, chamado http-server.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Alunos Front</title>
</head>
<body>
  <h1>Lista de alunos estático</h1>
  <ul>
    <ol>Nome: Aluno 1</ol>
    <ol>Nome: Aluno 2</ol>
    <ol>Nome: Aluno 3</ol>
    <ol>Nome: Aluno 4</ol>
  </ul>
</body>
</html>
npm install http-server -g

Depois de instalado, vamos ao terminal nossa de preferência, navegaremos até a nossa pasta alunos-front e rodaremos. Lembre-se que precisamos ter outra janela do terminal rodando nosso projeto de API simultaneamente ao projeto front:

Os dois projetos rodando juntos
http-server
Terminal rodando a aplicação alunos-front

Acessaremos nosso endereço para visualizar nosso html no endereço http://localhost:8080 ou http://127.0.0.1:8080.

Lista de alunos estática

O que falta para integrarmos com a nossa API? Falta fazermos a requisição, certo? Para isso vamos usar AJAX, para tornar as coisas dinâmicas.

Utilizaremos uma biblioteca famosa no mundo front-end para realizar essas requisições.

Essa lib é o axios 0.18.0 – ela tem a finalidade de realizar requisições e ser baseada em promises. Importaremos ela no nosso html através da cdn https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js.

Ela tem uso simples com a seguinte estrutura:

axios.get('enderecodaapi')
    .then(response => console.log(response)) //caso retorne um sucesso
    .catch(error => console.log(error)) //caso ocorra algum erro

Depois do axios, temos os verbos HTTP podendo ser axios.get, axios.post, axios.delete, onde cada método precisa receber como primeiro parâmetro a URL. O segundo é um parâmetro opcional, que são os dados que serão enviados para a API.

Vamos agora consumir nossa API utilizando o axios e visualizaremos o retorno dela no console do Chrome.

Nosso código alterado do front-end ficará assim:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Alunos Front</title>
</head>
<body>
  <h1>Lista de alunos estático</h1>
  <ul>
    <ol>Nome: Aluno 1</ol>
    <ol>Nome: Aluno 2</ol>
    <ol>Nome: Aluno 3</ol>
    <ol>Nome: Aluno 4</ol>
  </ul>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script>
  axios.get('http://localhost:3000/api/v1/alunos')
    .then(response => console.log(response))
    .catch(error => console.log(error))
</script>
</html>

Checando o que acontece com as alterações realizadas no front-end, ao darmos refresh na aplicação temos o seguinte:

Página utilizando axios

Como podemos perceber, ocorreu um erro. Esse erro é bem conhecido pela galera de front-end: o famigerado erro de CORS. Para resolver isso vamos fazer uma pequena mudança em nossa API.

Voltando para o terminal e navegando até a pasta onde está localizado nosso projeto de API, vamos instalar a biblioteca cors.

npm install cors

Quando finalizar a instalação, vamos adicionar essa lib como um middleware da nossa API. Ou seja, todas as requisições passarão antes por essa biblioteca.

const express = require('express') //importacao do pacote
const app = express() //instanciando express
const cors = require('cors')

const alunos = [
  {
    nome: 'Aluno1',
    idade: 12
  },
  {
    nome: 'Aluno2',
    idade: 13
  },
  {
    nome: 'Aluno3',
    idade: 14
  },
  {
    nome: 'Aluno4',
    idade: 15
  }
]

app.use(cors()) //habilitando cors na nossa aplicacao

app.get('/api/v1/alunos', function (req, res) { //endereco da requisicao onde e retornado hello world
  res.send(alunos)
})

app.listen(3000) //execucao do servidor

Com essas alterações realizadas e a nossa API rodando novamente, basta acessarmos nossa aplicação e atualizá-la para vermos o resultado.

Front-end requerendo da API

Agora obtivemos a resposta esperada. Recebemos os dados dos alunos, e com isso podemos criar nossa lista dinâmica.

Vamos criar uma função dentro da tag script, onde ela receberá uma lista de alunos e criará a lista com os nomes. Com essa função criada, basta substituir dentro do axios.get.then, o console.log pela nossa função.

Nosso html final será assim:

  • HTML finalizado, listando alunos de forma dinâmica
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Alunos Front</title>
</head>
<body>
  <h1>Lista de alunos estático</h1>
  <ul id="alunos">
  </ul>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script>
  axios.get('http://localhost:3000/api/v1/alunos')
    .then(response => criaListaDinamica(response.data))
    .catch(error => console.log(error))
  const criaListaDinamica = ( alunos ) => {
    const ulAlunos = document.getElementById('alunos')
    alunos.map(aluno => {
      const listaAluno = document.createElement('li')
      listaAluno.innerHTML = `Nome: ${aluno.nome}`
      ulAlunos.appendChild(listaAluno)
    })
  }
</script>
</html>

Agora temos uma noção geral de como construir um back-end e front-end separadamente e entendemos alguns conceitos por trás da construção de uma API.