O server side da aplicação foi implementado em forma de uma REST API em JavaScript, através do ambiente de execução de aplicação Node.js. A aplicação é utilizada pelo serviço do cliente como uma ponte para o banco de dados e, através do Express, é disponibilizado um conjunto de rotas pelas quais a aplicação do cliente poderá executar diferentes operações com os dados, como inserir, consultar ou alterar. Ao longo deste capítulo será explicado o passo a passo do desenvolvimento dessa REST API, além de explicitar o conjunto de rotas as quais o serviço atende e como podem ser utilizadas pelo cliente side.
3.2.1Configuração inicial do servidor
A configuração de um servidor web é o passo inicial de uma aplicação REST API, pois é nesse momento que o serviço começará a “ouvir” requisições vindas através da internet, mesmo que nada seja feito em seguida.
Atualmente, um dos principais frameworks para o desenvolvimento de API’s utilizando a linguagem de programação JavaScript é o Express. Através dele é possível definir parâmetros como a porta na qual o servidor estará ouvindo; o controle de acesso a API através de clientes externos, ou Cross-Origin Resource Sharing (CORS); o formato dos dados que serão utilizados nas comunicações; onde ficam pastas de acesso público (pastas com conteúdo estático); as rotas nas quais o cliente poderá executar operações na API, entre outros.
Para a API do Catalogue.me, em poucas linhas de código, todas essas configurações foram definidas. Como podemos ver no trecho de código da Figura 2, a aplicação está configurada utilizando o Express, e através do método use são passadas as informações. Através dessa sequência de linhas de código exibida logo abaixo, de cima para baixo, o serviço está sendo definido para:
a) dar acesso a todos as requisições externas;
b) realizar a comunicação entre cliente e servidor ocorre por meio do envio de objetos do tipo JavaScript Object Notation (JSON);
c) definir que as rotas de acesso à API estão em um arquivo à parte, e serão mostradas mais à frente;
d) definir que a pasta “./public” possui conteúdo estático a ser servido pela API;
e) e por último, a API foi configurada a ouvir requisições na porta 3333.
Código 1 – Configurações iniciais utilizando Express
1. const app = express();
2. app.options('*', cors());
3. app.use(function(req, res, next) {
4. res.header("Access-Control-Allow-Origin", "*");
5. res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
14. app.listen(process.env.PORT || 3333);
Fonte: Elaborado pelo autor (2021).
3.2.2 Configuração das rotas de acesso
A configuração das rotas é realizada também através do Express, pois nele temos um recurso chamado Router, que é uma função que utilizaremos para criar nossas rotas. Através do Router, primeiro temos que definir o tipo de requisição HTTP da rota, podendo ser de sete tipos:
GET, POST, HEAD, OPTIONS, PUT, DELETE e TRACE. Cada tipo de requisição tem uma característica e uma semântica, ou seja, para cada uma delas existe uma situação na qual faz mais sentido utilizá-la diante das outras. Os dois tipos mais utilizados são o POST e o GET, e ambos são utilizados neste projeto.
Após escolher o tipo da requisição, é necessário definir o caminho que indicará cada método da API, e isso é feito de forma bem simples, como podemos ver no código abaixo. A descrição da utilização de cada uma das 12 rotas da aplicação está dividida em dois arquivos de controle, um para as requisições que envolvem as lojas e outro para os produtos. Abaixo serão explicadas cada uma delas na sequência de cima para baixo:
26
Código 2 – Rotas de acesso para aplicação
1. const routes = express.Router();
2. const shopsController = new ShopsController();
3. const itemsController = new ItemsController();
4. requisição nesta rota a API tem o dever de cadastrar uma nova loja no banco de dados, e isso ocorre da seguinte forma: o cliente envia uma requisição do tipo POST que possui obrigatoriamente os três atributos name, whatsapp e passwd;
após receber esses três valores, a senha passa por um processo de criptografia, para melhorar a segurança do usuário, utilizando uma biblioteca do JavaScript crypto; o próximo passo é a inserção dos valores no banco de dados (a senha a ser inserida no banco de dados é o resultado da criptografia), para esse fim utiliza-se a biblioteca knex, que ajuda a gerenciar todo o acesso e comunicação com o banco. O retorno desse método é uma resposta com status 201 Created.
b) Esta rota é do tipo POST e é acionada pelo caminho /shops/edit. Como o caminho sugere, nessa requisição a API irá editar algum valor de uma loja já cadastrada. Para esta rota, são passados os parâmetros id, name e whatsapp e apenas será realizada uma busca na tabela shops através do id informado e um comando update, atualizando os valores da loja encontrada pelos valores recebidos na requisição. O knex novamente cuida do acesso ao banco de dados nas duas situações necessárias.
c) A terceira rota é do tipo GET, acionada pelo caminho /shops. Essa rota tem um papel bastante simples, retornar todas as lojas cadastradas no banco de dados.
Nenhum parâmetro é necessário para essa busca, o knex consegue acessar e retornar essas lojas com facilidade.
d) Nessa rota do tipo GET, a API tem o dever de retornar uma loja a partir de um id informado. Para acionar essa rota utiliza-se o caminho /shop/:id, onde o termo
“:id” significa que na própria rota deve existir um parâmetro chamado id, contento um valor. Um exemplo de acesso a uma rota com parâmetros é
“/shop/25”, onde a API entenderá o valor 25 como o parâmetro de nome id. A partir disso o trabalho da API é somente utilizar o knex para consultar no banco de dados uma loja que possua o id igual ao que será passado pela URL.
e) Essa rota também é do tipo GET e também utiliza um parâmetro e, de forma semelhante à rota anterior, captura o valor do parâmetro passado através da URL e utiliza o knex para consultar o banco de dados, mas dessa vez o atributo que será usado na busca é a tag. A tag é a representação da URL da loja (parte que vem após a URL base do sistema Catalogue.me), que é igual ao nome da loja sem espaços entre as palavras. Dessa forma, é possível utilizar a tag numa consulta pelo nome das lojas através de um pequeno ajuste na query.
f) A última requisição referente às lojas é a /login, uma requisição do tipo POST que é utilizada para autenticar o usuário no sistema. Para tal fim, é necessário que sejam informados dois atributos, whatsapp e passwd. De posse desses dois valores, criptografamos a senha utilizando o mesmo método do cadastro de lojas, e então é buscado no banco de dados uma loja que possua a combinação de valores de whatsapp e senha criptografada, iguais as obtidas anteriormente. Uma vez que seja possível encontrar uma loja correspondente, é criado um Json Web Token (JWT), utilizando a biblioteca jsonwebtoken do JavaScript. Esse token possui as informações de sessão do usuário agora autenticado, e será utilizado pelo cliente para iniciar uma sessão no navegador após o login.
g) O primeiro caminho utilizado pelo controlador responsável pelos produtos é o /items, uma requisição do tipo POST que cadastra um produto no banco de dados. Para o cadastro do item, é necessário que sejam informados os atributos name, price, info e shop_id, sendo o info o único opcional. Antes de entrar no
28
método create, a requisição passa por um middleware, que é um recurso do express para encadear funções durante o tratamento de uma requisição. Em resumo, um middleware é uma função que é executada antes da função principal da rota, e nesse caso a função a ser utilizada como middleware é a single, presente na biblioteca multer. Essa biblioteca é utilizada amplamente pelos desenvolvedores JavaScript para realizar o upload de arquivos para o servidor e aqui, com o auxílio de outra biblioteca do mesmo grupo chamada multer-s3, o multer terá a capacidade de realizar o upload de um arquivo não para o próprio servidor, mas para um bucket localizado nos servidores da Amazon S3, que foi previamente configurado. O acesso ao bucket da Amazon S3 é feito através da biblioteca aws-sdk e, caso exista um arquivo na requisição, o multer fará o upload corretamente. Nessa requisição, o arquivo em questão é uma imagem de capa para o item, que pode ou não ser informado no momento do cadastro. Após o tratamento dessa imagem, seguimos para a criação do item em si utilizando os atributos que foram obtidos na própria requisição junto da URL do arquivo salvo na Amazon (caso exista).
h) Nessa requisição, utiliza-se o caminho /avatar para inserir uma imagem em um produto já existente. Essa requisição é do tipo POST e utiliza o mesmo middleware da requisição anterior para fazer upload da imagem para a Amazon S3 antes de continuar com o processamento. Após esse passo, é utilizado apenas o id do produto para, através do knex, alterar o valor do campo avatar pela URL da imagem cadastrada.
i) A rota /items/edit é utilizada para editar as informações textuais de um produto, pois a sua imagem é alterada a partir da rota anterior. É uma rota do tipo POST, que recebe as informações de name, price e info, além do id do produto, e utiliza o knex para realizar um update simples das informações.
j) Através dessa rota é possível excluir um produto cadastrado. Utilizando o caminho /items/delete numa requisição do tipo POST, e informando o id do produto, a operação poderá ser realizada corretamente através de uma chamada do método delete do knex.
k) A rota /items/inative, do tipo POST, modifica o status de estoque de um produto.
Através do id do item, um update é realizado no knex, verificando o valor atual de estoque do produto e alterando para o valor contrário.
l) Finalmente na última rota, um GET que é acionado pelo caminho /items, o cliente recebe um vetor com todos os produtos de uma loja, informando apenas o id da loja desejada. O knex consegue realizar essa tarefa com uma simples query ao banco de dados.
3.2.3 Hospedagem da aplicação
A aplicação da REST API se encontra hospedada no Heroku, através de um plano gratuito, apenas as imagens estão nos servidores da Amazon S3, em um bucket criado para esta plataforma. Todo o código se encontra na plataforma Github.