Artigo original: REST API Tutorial – REST Client, REST Service, and API Calls Explained With Code Examples
Você já se perguntou como funciona o login/inscrição em um site da web no back-end? Ou ainda, quando você procura por "gatinhos fofinhos" no YouTube, você recebe vários resultados e consegue reproduzi-los pelo stream a partir de uma máquina remota?
Neste guia para iniciantes, mostrarei para você o processo de configurar uma API RESTful. Tiraremos do caminho um pouco do jargão e examinaremos como programar um servidor no NodeJS. Vamos analisar mais a fundo o JavaScript!
Tirando o jargão do caminho
Então, o que é REST? De acordo com a Wikipédia:
Representational state transfer (REST), em português Transferência Representacional de Estado, é um estilo de arquitetura de software que define um conjunto de restrições a serem usadas na criação de Web services (serviços Web). Os Web Services que estão em conformidade com o estilo arquitetural REST, denominados Web services RESTful,... permitem que os sistemas solicitantes acessem e manipulem representações textuais dos recursos da web usando um conjunto uniforme e predefinido de operações sem estado
Vamos desmistificar o conteúdo (esperamos que você tenha lido tudo isso). REST é, basicamente, um conjunto de regras de comunicação entre um client e um servidor. Existem algumas restrições na definição de REST:
- Arquitetura client-servidor: a interface de usuário do site da web/aplicação deve ser separada da solicitação/armazenamento dos dados, de modo que cada parte possa ser dimensionada individualmente.
- Ausência de estado: a comunicação não deve ter um contexto de client armazenado no servidor. Isso quer dizer que cada solicitação ao servidor deve ser feita com todos os dados solicitados e que não se deve presumir que o servidor possua dados de solicitações anteriores.
- Sistema em camadas: o client não deve poder distinguir se está se comunicando diretamente com o servidor ou por meio de algum intermediário. Esses servidores intermediários (sejam um proxy, sejam balanceadores de carga) permitem a escalabilidade e a segurança do servidor subjacente.
Certo, agora que sabemos o que são os sistemas RESTful (em conformidade com o padrão REST), explicaremos alguns dos termos que usamos no título:
- Client REST: código ou uma aplicação que pode acessar esses serviços REST. Você está usando um nesse exato momento! Sim, o navegador pode agir como um client REST não controlado (o site da web trata das solicitações do navegador). O navegador, por muito tempo, usava uma função integrada chamada XMLHttpRequest para todas as solicitações REST. Agora, essa função teve como sua sucessora a FetchAPI, uma abordagem moderna e baseada em promises às solicitações. Outros exemplos são bibliotecas de código, como o axios, o superagent e o got, ou ainda algumas aplicações dedicadas, como o Postman (ou sua versão on-line, o Hoppscotch), ou uma ferramenta de linha de comando como o cURL!
- Serviço REST: o servidor. Existem muitas bibliotecas populares que tornam fácil a criação desses servidores, como o ExpressJS para NodeJS e o Django para Python.
- API REST: este termo define o endpoint e os métodos que têm permissão de acesso/envio de dados ao servidor. Falaremos sobre isso em mais detalhes abaixo. Outras alternativas são o GraphQL, o JSON-Pure e o oData.
Ok, mas qual é a aparência do REST?
Em termos muito genéricos, você pode pedir ao servidor uma determinada quantidade de dados ou pedir que ele grave alguns dados. O servidor, então, responde às suas solicitações.
Em termos de programação, existe um endpoint (um URL) em que o servidor aguarda para receber uma solicitação. Nos conectamos àquele endpoint e enviamos alguns dados a nosso respeito (lembre-se de que REST não tem estado - é stateless - o que não permite que dados sobre a solicitação sejam armazenados) e o servidor responde com a resposta correta.
Falar é fácil, vamos fazer uma demonstração. Usarei o Postman para mostrar uma solicitação e uma resposta:

Os dados retornados estão no formato JSON (JavaScript Object Notation) e podem ser acessados diretamente.
Aqui, temos https://official-joke-api.appspot.com/random_joke
, que é chamado de endpoint da API. Existirá um servidor escutando por solicitações àquele endpoint, como aquela que acabamos de fazer.
Anatomia do REST:
Certo, agora que sabemos que os dados podem ser solicitados pelo client e que o servidor responderá de modo adequado, vamos examinar como uma solicitação é feita.
- Endpoint: essa, nós já sabemos. Para relembrar, no entanto, o endpoint é o URL onde o servidor REST está à escuta de solicitações.
- Método: antes, eu disse que é possível solicitar dados ou modificá-los. No entanto, como o servidor sabe qual o tipo de operação o client quer realizar? O REST implementa diversos "métodos" para os diferentes tipos de solicitação, sendo os métodos abaixo os mais conhecidos:
- GET: obter (em inglês, get) recursos de um servidor.
- POST: criar (ou "publicar" - em inglês, post) recursos em um servidor.
- PATCH ou PUT: atualizar o recurso existente em um servidor.
- DELETE: excluir (em inglês, delete) um recurso de um servidor. - Cabeçalhos: os detalhes adicionais fornecidos para a comunicação entre client e servidor (lembre-se, o REST é stateless). Alguns dos cabeçalhos comuns são:
Solicitação:
- host: o IP do client (ou de onde veio a solicitação)
- accept-language: linguagem compreensível pelo client
- user-agent: dados sobre o client, sistema operacional e fornecedor
Resposta:
- status: o status da solicitação ou código HTTP.
- content-type: tipo de recurso enviado pelo servidor.
- set-cookie: definição dos cookies pelo servidor. - Dados: (também chamados de corpo - body - ou de mensagem - message) contêm as informações que você quer enviar ao servidor.
Chega de detalhes – eu quero ver o código.
Vamos começar a programar um serviço REST no Node. Implementaremos tudo o que aprendemos acima. Usaremos a ES6+ para escrever/criar nosso serviço.
Não se esqueça de instalar o Node.JS e fazer com que o node
e o npm
estejam disponíveis no caminho que você criará. Usarei o Node 12.16.2 e o NPM 6.14.4.
Crie um diretório rest-service-node
e entre nele usando cd
, assim:
mkdir rest-service-node
cd rest-service-node
Inicialize o projeto do node:
npm init -y
A flag -y
evita uma série de perguntas iniciais. Se quiser preencher todo o questionário, digite apenas npm init
.
Vamos instalar alguns pacotes. Usaremos o framework ExpressJS para desenvolver o servidor REST. Execute o comando abaixo para instalá-lo:
npm install --save express body-parser
Para que serve o body-parser
? O Express, por padrão, não consegue lidar com os dados enviados por uma solicitação POST como JSON. O body-parser
permite que o Express resolva essa questão.
Nota do tradutor: depois da atualização para a versão 4 do Express, body-parser deixou de ser necessário e o Express agora consegue fazer por si o que antes necessitava do body-parser para realizar. Isso significa que o comando acima pode ser, simplesmente, npm install --save express
Crie um arquivo chamado server.js
e adicione o código abaixo:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.listen(5000, () => {
console.log(`Server is running on port 5000.`);
});
Nota do tradutor: a partir da versão 4 do Express, a segunda linha do código (const bodyParser = require("body-parser");
) não é mais necessária e você pode substituir a linha que dizapp.use(bodyParser.json());
porapp.use(express.json());
.
As duas primeiras linhas são as importações de Express e de body-parser.
A terceira linha inicializa o servidor do Express e o define como uma variável chamada app
.
A linha, app.use(bodyParser.json());
inicializa o plug-in do body-parser (ver notas do tradutor acima).
Por fim, definimos que nosso servidor escute solicitações vindas da porta 5000
.
Obtendo dados do servidor REST:
Para obter dados de um servidor, precisamos de uma solicitação GET
. Adicione o código a seguir antes de app.listen
:
const sayHi = (req, res) => {
res.send("Hi!");
};
app.get("/", sayHi);
Criamos uma função sayHi
, que recebe dois parâmetros, req
e res
(explicaremos isso mais tarde) e envia um 'Hi!' como resposta.
app.get()
recebe dois parâmetros, o caminho de rota e a função a ser chamada quando o caminho é solicitado pelo client. Assim, a última linha pode ser traduzida como: Oi, servidor, escute as solicitações em '/' (leia-se página inicial) e chame a função sayHi
se uma solicitação for feita.
app.get
também nos dá um objeto request
, contendo todos os dados enviados pelo client, e um objeto response
, com todos os métodos através dos quais podemos responder ao client. Embora eles estejam acessíveis como parâmetros da função, a convenção de nomeação geral sugere que demos o nome de res
para response
e req
para request
.
Chega de papo. Hora de iniciar o servidor! Execute o comando abaixo:
node server.js
Se tudo der certo, você deverá ver uma mensagem no console dizendo: Server is running on port 5000.
Nota: você pode alterar a porta para o número que você quiser.

Abra seu navegador e acesse http://localhost:5000/
. Você deverá ver algo assim:

Aí está! Sua primeira solicitação de GET
foi um sucesso!
Enviando dados para um servidor REST:
Como discutimos anteriormente, vamos definir como implementar uma solicitação de POST
em nosso servidor. Enviaremos dois números e o servidor retornará a soma desses números. Adicione este novo método abaixo em app.get
:
app.post("/add", (req, res) => {
const { a, b } = req.body;
res.send(`The sum is: ${a + b}`);
});
Aqui, enviaremos os dados em formato JSON, assim:
{
"a":5,
"b":10
}
O que está dizendo o código:
Na linha 1, estamos invocando o método .post()
do ExpressJS, que permite que o servidor escute solicitações de POST
. Essa função recebe os mesmos parâmetros que o método .get()
. A rota que passaremos é /add
, de modo que seja possível acessar o endpoint como http://your-ip-address:port/add
, ou, em nosso caso, localhost:5000/add
. Colocamos nossa função em linha em vez de escrever a função em outro lugar.
Na linha 2, usamos um pouco da sintaxe da ES6 - especificamente, desestruturação de objetos. Todos os dados que enviarmos por meio de solicitação serão armazenados e ficarão disponíveis no body
do objeto req
. Por isso, essencialmente, poderíamos ter substituído a linha 2 por algo do tipo:
const num1 = req.body.a;
const num2 = req.body.b;
Na linha 3, usaremos a função send()
do objeto res
para enviar o resultado da soma. Novamente, estaremos usando as template literals da ES6. Hora de fazer o teste (usando o Postman):

Desse modo, enviamos os dados 5 e 10 como a
e b
, usando-os no corpo da solicitação. O Postman anexa esses dados à solicitação e a envia. Quando o servidor recebe a solicitação, ele analisa os dados de req.body
, como fizemos com o código acima. O resultado é exibido na parte inferior da imagem.
Certo, vamos para a parte final do código:
const express = require("express");
// A linha a seguir não é necessária a partir da versão 4 do Express
const bodyParser = require("body-parser");
const app = express();
// A partir da versão 4 do Express, é possível substituir a linha abaixo por app.use(express.json());
app.use(bodyParser.json());
const sayHi = (req, res) => {
res.send("Hi!");
};
app.get("/", sayHi);
app.post("/add", (req, res) => {
const { a, b } = req.body;
res.send(`The sum is: ${a + b}`);
});
app.listen(5000, () => {
console.log(`Server is running on port 5000.`);
});
Client REST:
Pois bem, criamos um servidor, mas como o acessamos a partir do nosso site da web ou aplicação? Aqui, as bibliotecas de client REST são úteis.
Estamos criando uma página da web que contém um formulário, onde você poderá inserir dois números e exibiremos o resultado. Vamos começar.
Primeiro, vamos alterar um pouco o arquivo server.js
:
const path = require("path");
const express = require("express");
// A linha a seguir não é necessária a partir da versão 4 do Express
const bodyParser = require("body-parser");
const app = express();
// A partir da versão 4 do Express, é possível substituir a linha abaixo por app.use(express.json());
app.use(bodyParser.json());
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "index.html"));
});
app.post("/add", (req, res) => {
const { a, b } = req.body;
res.send({
result: parseInt(a) + parseInt(b)
});
});
app.listen(5000, () => {
console.log(`Server is running on port 5000.`);
});
Importamos um novo pacote, path
, fornecido pelo Node, para manipular paths (caminhos) entre plataformas. Em seguida, alteramos a solicitação de GET
em '/' e usamos outra função disponível em res
, chamada sendFile
. Essa função permite que enviemos qualquer tipo de arquivo como resposta. Desse modo, sempre que uma pessoa tentar acessar '/', ela receberá nossa página index.html
.
Por fim, alteramos nossa função app.post
para que retorne a soma como JSON e converta a
e b
em números inteiros.
Vamos criar uma página html, que chamaremos de index.html
, com um estilo básico:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>REST Client</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
form {
display: flex;
flex-direction: column;
margin-bottom: 20px;
}
label,
input[type="submit"] {
margin-top: 20px;
}
</style>
<body>
<div class="container">
<h1>Simple POST Form</h1>
</h1>
<form>
<label>Number 1:</label>
<input id="num1" type="number" />
<label>Number 2:</label>
<input id="num2" type="number" />
<input type="submit" value="Add"/>
</form>
<div class="result">Click Add!</div>
</div>
</body>
</html>
Vamos adicionar a ela uma tag script
antes da tag de fechamento de body, para que não precisemos manter um arquivo .js
. Começaremos escutando pelo evento de submit
e chamaremos uma função quando esse evento ocorrer:
<script>
document.addEventListener("submit", sendData);
</script>
Primeiro, precisamos evitar que a página seja atualizada quando o botão "Add" for clicado. Isso pode ser feito usando a função preventDefault()
. Em seguida, obteremos o valor das entradas (dos elementos input) naquele instante:
function sendData(e) {
e.preventDefault();
const a = document.querySelector("#num1").value;
const b = document.querySelector("#num2").value;
}
Faremos a chamada ao servidor com esses valores, a
e b
. Usaremos a Fetch API, integrada em todos os navegadores, para isso.
Fetch recebe duas entradas, o URL do endpoint e um objeto de solicitação em JSON, e retorna uma promise. Explicar ambos aqui é um pouco fora dos limites deste tutorial. Deixamos os links da MDN para você ler a respeito, portanto.
Continuando na função sendData()
:
fetch("/add", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
a: parseInt(a),
b: parseInt(b)
})
})
.then(res => res.json())
.then(data => {
const {
result
} = data;
document.querySelector(
".result"
).innerText = `The sum is: ${result}`;
})
.catch(err => console.log(err));
Primeiro, passamos o URL relativo ao endpoint como o primeiro parâmetro de fetch
. Em seguida, passamos um objeto que contém o método que queremos que seja utilizado por Fetch para a solicitação - neste caso, POST
.
Também passamos headers
(os cabeçalhos), que fornecerão as informações sobre o tipo de dados que estamos enviando (content-type
) e o tipo de dados que aceitaremos como resposta (accept
).
Depois, disso, passamos o body
. Lembra-se de que digitamos os dados como JSON quando usamos o Postman? Estamos fazendo algo semelhante aqui. Como o Express trata das entradas como strings e as processa de acordo com o content-type fornecido, precisamos converter nossa carga em JSON para uma string. Fazemos isso com JSON.stringify()
. Estamos, na verdade, adicionando um cuidado a mais e transformando as entradas em números inteiros, de maneira a não causar confusão com o servidor (já que não implementamos nada que sirva como verificação de tipos de dados).
Por fim, se a promise (retornada por fetch) for resolvida, receberemos aquela resposta e a converteremos em JSON. Depois disso, receberemos o resultado de data
retornado pela resposta. Aí, é uma simples questão de exibir o resultado na tela.
No fim, se a promise for rejeitada, exibiremos a mensagem de erro no console.
Este é o código final para index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>REST Client</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
form {
display: flex;
flex-direction: column;
margin-bottom: 20px;
}
label,
input[type="submit"] {
margin-top: 20px;
}
</style>
<body>
<div class="container">
<h1>Simple POST Form</h1>
</h1>
<form>
<label>Number 1:</label>
<input id="num1" type="number" />
<label>Number 2:</label>
<input id="num2" type="number" />
<input type="submit" value="Add"/>
</form>
<div class="result">Click Add!</div>
</div>
<script>
document.addEventListener("submit", sendData);
function sendData(e) {
e.preventDefault();
const a = document.querySelector("#num1").value;
const b = document.querySelector("#num2").value;
fetch("/add", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
a: parseInt(a),
b: parseInt(b)
})
})
.then(res => res.json())
.then(data => {
const { result } = data;
document.querySelector(
".result"
).innerText = `The sum is: ${result}`;
})
.catch(err => console.log(err));
}
</script>
</body>
</html>
Conclusão:
Neste artigo, aprendemos sobre a arquitetura REST e sobre a anatomia de solicitações REST. Fizemos a criação de um servidor REST simples, que atende a solicitações GET
e POST
, e criamos uma página da web simples que usa um client REST para exibir a soma de dois números.
Você pode estender isso e usar os tipos restantes de solicitações e até mesmo implementar uma aplicação com CRUD no back-end completa (texto de referência em inglês).
Espero que você tenha aprendido algo com este artigo. Se tiver perguntas, fique a vontade de conversar com o autor pelo Twitter! Feliz programação!