Atualizado: 02/01/2025

Criando uma API - Node.js

Usando Express e Node.js, podemos implementar uma API completa no conceito REST para interagir com o usuário. A arquitetura REST propõe a aplicação dos seguintes métodos ou tipos de requisições HTTP para interagir com o servidor:

  • GET: obter informações do servidor

  • POST: enviar informações para o servidor

  • PUT: atualizar informações no servidor

  • DELETE: remover informações do servidor

O REST é especialmente conveniente ao criar qualquer tipo de Single Page Application. Vamos ver como criar nossa própria API. Para um novo projeto, vamos criar uma nova pasta. Em seguida, adicionaremos o pacote express ao projeto usando o comando:

npm install express

Neste caso, vamos criar um projeto experimental, que demonstrará a aplicação de REST em uma aplicação usando Node.js e Express. Para processar as requisições, vamos definir o seguinte arquivo app.js:

const express = require("express");
     
const app = express();
app.use(express.json());
    
app.use(express.static("public"));
  
// Base de dados condicional
const users = [];
let id = 1;  // para definir identificadores
  
// Função auxiliar para encontrar o índice do usuário pelo id
function findUserIndexById(id) {
    for(let i = 0; i < users.length; i++) {
        if(users[i].id == id) return i;
    }
    return -1;
}

app.get("/api/users", function(_, res) {
    res.send(users);
});

// Obtenção de um usuário pelo id
app.get("/api/users/:id", function(req, res) {
    const id = req.params.id; // Obtendo o id
    // Encontrando o usuário no array pelo id
    const index = findUserIndexById(id);
    // Enviando o usuário
    if(index > -1){
        res.send(users[index]);
    } else {
        res.status(404).send("User not found");
    }
});

// Recebendo dados enviados
app.post("/api/users", function (req, res) {
    if(!req.body) return res.sendStatus(400);
    
    const userName = req.body.name;
    const userAge = req.body.age;
    const user = { name: userName, age: userAge };
    // Atribuindo o identificador da variável id e incrementando
    user.id = id++;
    // Adicionando o usuário ao array
    users.push(user);
    res.send(user);
});

// Removendo usuário pelo id
app.delete("/api/users/:id", function(req, res) {
    const id = req.params.id;
    const index = findUserIndexById(id);
    if(index > -1) {
        // Removendo o usuário do array pelo índice
        const user = users.splice(index, 1)[0];
        res.send(user);
    } else {
        res.status(404).send("User not found");
    }
});

// Alterando usuário
app.put("/api/users", function(req, res) {
    if(!req.body) return res.sendStatus(400);
    
    const id = req.body.id;
    const userName = req.body.name;
    const userAge = req.body.age;
    
    const index = findUserIndexById(id);
    if(index > -1) {
        // Alterando os dados do usuário
        const user = users[index];
        user.age = userAge;
        user.name = userName;
        res.send(user);
    } else {
        res.status(404).send("User not found");
    }
});
    
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));

Nesta aplicação, para simplificar, utilizaremos um array simples users como um banco de dados. Por padrão, ele está vazio:

const users = [];

Cada objeto que será adicionado a este array terá um identificador numérico específico. Para definir os identificadores dos objetos ao criá-los, definimos a variável id:

let id = 1;

Também precisaremos de uma função auxiliar para encontrar o índice de um usuário pelo id:

function findUserIndexById(id) {
  for (let i = 0; i < users.length; i++) {
      if (users[i].id == id) return i;
  }
  return -1;
}

Se o usuário for encontrado, será retornado o índice dele. Se não for encontrado, será retornado o número -1.

Para processar as requisições, foram definidos cinco métodos para cada tipo de requisição: app.get(), app.post(), app.delete() e app.put().

Quando a aplicação recebe uma requisição do tipo GET no endereço api/users, é acionado o seguinte método:

app.get("/api/users", function(req, res) {
  res.send(users);
});

Como resultado do processamento, devemos enviar o array de usuários usando o método res.send().

De maneira semelhante, funciona outro método app.get(), que é acionado quando o id do usuário é especificado no endereço:

app.get("/api/users/:id", function(req, res) {
  const id = req.params.id; // Obtendo o id
  // Encontrando o usuário no array pelo id
  const index = findUserIndexById(id);
  // Enviando o usuário
  if (index > -1) {
      res.send(users[index]);
  } else {
      res.status(404).send("User not found");
  }
});

A única diferença neste caso é que precisamos encontrar o usuário desejado pelo id no array. Se ele não for encontrado, retornamos o código de status 404: res.status(404).send().

Ao receber uma requisição do tipo POST, extraímos os dados enviados pelo cliente da seguinte maneira:

app.post("/api/users", function(req, res) {
  if (!req.body) return res.sendStatus(400);
  
  const userName = req.body.name;
  const userAge = req.body.age;
  const user = { name: userName, age: userAge };
  // Atribuindo o identificador da variável id e incrementando
  user.id = id++;
  // Adicionando o usuário ao array
  users.push(user);
  res.send(user);
});

Como no início do arquivo configuramos o parsing automático para JSON na pipeline de processamento das requisições, o corpo da requisição será um objeto JSON, do qual podemos extrair as propriedades name e age para criar o objeto usuário. Para definir o identificador, usamos a variável global id, cujo valor é incrementado.

Ao remover um usuário, realizamos ações semelhantes, mas agora extraímos do array o objeto que será removido:

// Removendo usuário pelo id
app.delete("/api/users/:id", function(req, res) {
    const id = req.params.id;
    const index = findUserIndexById(id);
    if (index > -1) {
        // Removendo o usuário do array pelo índice
        const user = users.splice(index, 1)[0];
        res.send(user);
    } else {
        res.status(404).send("User not found");
    }
});

Se o usuário não for encontrado, retornamos o código de status 404.

Se precisarmos alterar um usuário, usamos o método app.put:


app.put("/api/users", function(req, res) {
    if (!req.body) return res.sendStatus(400);
    
    const id = req.body.id;
    const userName = req.body.name;
    const userAge = req.body.age;
    
    const index = findUserIndexById(id);
    if (index > -1) {
        // Alterando os dados do usuário
        const user = users[index];
        user.age = userAge;
        user.name = userName;
        res.send(user);
    } else {
        res.status(404).send("User not found");
    }
});

Para buscar o objeto a ser alterado, encontramos seu índice pelo id, obtemos o objeto pelo índice e modificamos suas propriedades.

Assim, definimos a API mais simples possível. Agora, vamos adicionar o código do cliente. Conforme estabelecido no código, o Express utiliza a pasta public para armazenar arquivos estáticos. Portanto, criaremos essa pasta no projeto. Dentro dessa pasta, definiremos um novo arquivo index.html, que atuará como cliente. No final, todo o projeto terá a seguinte estrutura:

meu-projeto
│
├── app.js
│
├── package.json
│
├── node_modules
│
└── public
    └── index.html

Em seguida, definiremos o seguinte código no arquivo index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Programício</title>
    <style>
        td, th {padding: 5px; min-width: 90px; max-width: 200px; text-align: start;}
        .btn {padding: 4px; border: 1px solid #333; background-color: #eee; border-radius: 2px; margin: 5px; cursor: pointer;}
    </style>
</head>
<body>
    <h2>Lista de Usuários</h2>
    <form name="userForm">
        <input type="hidden" name="id" value="0" />
        <p>
            <label>Nome:</label><br>
            <input name="name" />
        </p>
        <p>
            <label>Idade:</label><br>
            <input name="age" type="number" />
        </p>
        <p>
            <button id="submitBtn" type="submit">Salvar</button>
            <button id="resetBtn">Resetar</button>
        </p>
    </form>
    <table>
        <thead><tr><th>Id</th><th>Nome</th><th>Idade</th><th></th></tr></thead>
        <tbody></tbody>
    </table>
    <script>
        const tbody = document.querySelector("tbody");

        // Obtenção de todos os usuários
        async function getUsers() {
            const response = await fetch("/api/users", {
                method: "GET",
                headers: { "Accept": "application/json" }
            });

            if (response.ok === true) {
                const users = await response.json(); 
                users.forEach(user => {
                    tbody.append(row(user));
                });
            }
        }

        // Obtenção de um usuário
        async function getUser(id) {
            const response = await fetch("/api/users/" + id, {
                method: "GET",
                headers: { "Accept": "application/json" }
            });
            if (response.ok === true) {
                const user = await response.json();
                const form = document.forms["userForm"];
                form.elements["id"].value = user.id;
                form.elements["name"].value = user.name;
                form.elements["age"].value = user.age;
            }
        }

        // Adição de usuário
        async function createUser(userName, userAge) {
            const response = await fetch("api/users", {
                method: "POST",
                headers: { "Accept": "application/json", "Content-Type": "application/json" },
                body: JSON.stringify({ name: userName, age: parseInt(userAge, 10) })
            });
            if (response.ok === true) {
                const user = await response.json();
                reset();
                tbody.append(row(user));
            }
        }

        // Edição de usuário
        async function editUser(userId, userName, userAge) {
            const response = await fetch("api/users", {
                method: "PUT",
                headers: { "Accept": "application/json", "Content-Type": "application/json" },
                body: JSON.stringify({ id: userId, name: userName, age: parseInt(userAge, 10) })
            });
            if (response.ok === true) {
                const user = await response.json();
                reset();
                document.querySelector(`tr[data-rowid="${user.id}"]`).replaceWith(row(user));
            }
        }

        // Remoção de usuário
        async function deleteUser(id) {
            const response = await fetch("/api/users/" + id, {
                method: "DELETE",
                headers: { "Accept": "application/json" }
            });
            if (response.ok === true) {
                const user = await response.json();
                document.querySelector(`tr[data-rowid="${user.id}"]`).remove();
            }
        }
        
        // Resetar formulário
        function reset() {
            const form = document.forms["userForm"];
            form.reset();
            form.elements["id"].value = 0;
        }

        // Criação de linha para a tabela
        function row(user) {
            const tr = document.createElement("tr");
            tr.setAttribute("data-rowid", user.id);
                
            const idTd = document.createElement("td");
            idTd.append(user.id);
            tr.append(idTd);
                
            const nameTd = document.createElement("td");
            nameTd.append(user.name);
            tr.append(nameTd);
                
            const ageTd = document.createElement("td");
            ageTd.append(user.age);
            tr.append(ageTd);
                
            const linksTd = document.createElement("td");
                
            const editLink = document.createElement("a");
            editLink.setAttribute("data-id", user.id);
            editLink.setAttribute("class", "btn");
            editLink.append("Editar");
            editLink.addEventListener("click", e => {
                e.preventDefault();
                getUser(user.id);
            });
            linksTd.append(editLink);
                
            const removeLink = document.createElement("a");
            removeLink.setAttribute("data-id", user.id);
            removeLink.setAttribute("class", "btn");
            removeLink.append("Deletar");
            removeLink.addEventListener("click", e => {
                e.preventDefault();
                deleteUser(user.id);
            });
                
            linksTd.append(removeLink);
            tr.appendChild(linksTd);
                
            return tr;
        }

        // Resetar valores do formulário
        document.getElementById("resetBtn").addEventListener("click", e => {
            e.preventDefault();
            reset();
        });

        // Envio do formulário
        document.forms["userForm"].addEventListener("submit", e => {
            e.preventDefault();
            const form = document.forms["userForm"];
            const id = form.elements["id"].value;
            const name = form.elements["name"].value;
            const age = form.elements["age"].value;
            if (id == 0)
                createUser(name, age);
            else
                editUser(id, name, age);
        });

        // Carregar usuários
        getUsers();
    </script>
</body>
</html>

A lógica principal está contida no código JavaScript. Ao carregar a página no navegador, todos os objetos são obtidos do banco de dados pela função getUsers:

async function getUsers() {
  // Envia a requisição e obtém a resposta
  const response = await fetch("/api/users", {
      method: "GET",
      headers: { "Accept": "application/json" {
  {);
  // Se a requisição for bem-sucedida
  if (response.ok === true) {
      // Obtém os dados
      const users = await response.json();
      users.forEach(user => {
          // Adiciona os elementos recebidos na tabela
          tbody.append(row(user));
      {);
  {
{

Para adicionar linhas na tabela, utilizamos a função row(), que retorna uma linha. Nesta linha, são definidas as referências para editar e remover um usuário.

Para obter um usuário específico, usamos a função getUser():

async function getUser(id) {
  const response = await fetch("/api/users/" + id, {
      method: "GET",
      headers: { "Accept": "application/json" }
  });
  if (response.ok === true) {
      const user = await response.json();
      const form = document.forms["userForm"];
      form.elements["id"].value = user.id;
      form.elements["name"].value = user.name;
      form.elements["age"].value = user.age;
  }
}

O usuário específico é adicionado ao formulário acima da tabela. Este mesmo formulário é utilizado tanto para adicionar quanto para editar um objeto. Com um campo oculto que armazena o id do usuário, podemos determinar qual ação está sendo executada: adicionar ou editar. Se o id for igual a 0, a função createUser é executada, enviando os dados em uma requisição POST:

async function createUser(userName, userAge) {
  const response = await fetch("api/users", {
      method: "POST",
      headers: { "Accept": "application/json", "Content-Type": "application/json" },
      body: JSON.stringify({
          name: userName,
          age: parseInt(userAge, 10)
      })
  });
  if (response.ok === true) {
      const user = await response.json();
      reset();
      tbody.append(row(user));
  }
}

Se o usuário já foi carregado no formulário e seu id está armazenado no campo oculto, a função editUser é executada, enviando uma requisição PUT:

Ao executar a aplicação e acessar no navegador o endereço http://localhost:3000, será possível adicionar, editar e remover usuários:

Criando uma API em Express e Node.js
Aplicando REST em Express e Node.js
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com