API's Rest

Estado de Transferência representativo.

Estados

Entidades

Os dados circularam entre Servidor REST e Cliente essa articulação sera realizada sempre por uma requisição que devolvera sempre uma resposta.

Essas serão direcionadas sempres aos verbos HTTP (get, post, delete, patch). E cada um desses verbos estão relacionados a end-points ou simplesmente URL's.

Requisições e Respostas geralmente transitam em formato JSON, mas podem assumir tranquilamente outros formatos como: XML, FormData, URLEncoded...

Preparando Ambiente

No terminal:

JSON

Para iniciar o projeto utilize o npm com o comando init ou init -y isso criará o arquivo package.JSON que ira abrigar todos os dados do projeto.

npm init

Express

Dentro dele executaremos o servidor para isso usaremos o modulo "Express" que permite criar e executar servidores a partir dele. Sendo o corpo para requisições HTTP no NODE.

O comando a ser utilizado é o npm install.

npm install express
Funcionais

Body Parser

converte entradas em objetos diversos JSON e JS.

npm install body-parser

MySQL

Permite a conexão entre o API rest e o MySQL

npm install mysql

Sequelize

npm install sequelize

Arquivo Principal

Criado enter point geralmente utilize o nome "index.js" ou "sever.js"

    const http = require('http');
    const app = require('./app')
    const port = process.env.PORT || 3000;
    const server = http.createServer(app);
    server.listen(port);
                    

Defina um arquivo app.js caso siga o modelo, como pode notar no arquivo acima o mesmo de encontra na mesma pasta do arquivo principal.

Portas

Para a API funcionar defina um escutador para as requisições do servidor.
Esse escutador recebe uma porta e em seguida uma Função que serve como um callback simples para teste.

                        app.listen(3000, função)
                    ex:
                        app.listen(3000, () => console.log('servidor na porta 3000 ok'))
                        

Arquivo APP

Este fica responsavel por mediar as rotas contendo arquivos de conexão.

Definindo Express

Chamando módulo do express, defina uma variavel para melhorar a visualização do codigo. O mesmo deve ser requerido.
Após defina também sua instância.

    const express = require('express')
    const app = express()
                    

A partir desse novo arquivo app é possível definir as rotas de novos arquivos responsáveis por entregar diversas funções.

    const express = require('express')
    const app = express()

    const rota = require('./pasta/arquivo')
    app.use('/definiCaminhoURL', rota);

    module.exports = app;
                    

Definindo Body parser

O mesmo sera usado como um plugin, então após a requisição usar ele no app usando a chamada do .json() como função, pois sera o formato de trabalho.

        ...
    const app = express()
    const bodyParser = require('body-parser')

    app.use(body-parser.urlencoded({extended: false})) <-só dados simples
    app.use(bodyParser.json()) <- entrada json
                    

Definindo Cabeçalhos / Tratando erros CORS

Essas configurações dizem respeito as permissões que são concedidas ao client permitindo definições como; tipos de requisições aceitas, formado aceito, autorizações de acesso...

app.use((req, res, next)=>
{
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Header', 'Origin, X-Requrested-With, Content-Type, Accept, Authorization');
    
    if (req.method === 'OPITONS') {
        res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, PATCH, DELETE');
        return res.status(200).send({});
    }
    next();
});
                        

Arquivo de Conexão

Definindo MySQL

Conectando com o Banco de Dados

Defina um arquivo para o BD para manter as boas praticas. Nele importe o modulo do MySQL e em seguida passe os dados da conexão através do createConnection() ou de um createPool().

    const mysql = require('mysql')

    const conexao = mysql.createConnection(
        {
            host: 'localhost',
            port: 3306,
            user: 'root',
            password: 'admin',
            database: 'agenda'
        }
    )
    
    module.exports = conexao
                    
    const mysql = require('mysql')

    const pool = mysql.createPool(
        {
            "user" : "root",
            "password": "admin",
            "database" : "lojinha",
            "host": "localhost",
            "port": 3306
        }
    )
    
    exports.pool = pool
                    

Importante notar que as credenciais do banco de dados devem ser passadas por instâncias protegidas, pratica passe sempre variáveis de ambiente.

Sequelize (complemento ORM)

Comunicando com Banco de dados

Criar arquivo .js de comunicação de preferencia em uma pasta separada para conexão. O modulo Sequelize sera o responsável por essa comunicação.

                        const Sequelize = require('sequelize')
                    declarando instância:
                        const instancia = new Sequelize()
                    
                        module.exports = instancia
                        

As configurações do acesso ao banco de dados vai dentro da instância.

                    
                            ...
                        const instancia = new Sequelize(
                                'nome_bancoDados',
                                'usuario',
                                'senha',
                                {
                    host: 'ip_maquina',
                    dialect: 'tipode_BancoDados'
                                }
                            
                        )
                        
                        module.exports = instancia
                        
                            ...
                        const config = require('config')
                        const instancia = new Sequelize(
                            config.get('mysql.banco-de-dados'),
                            config.get('mysql.usuario'),
                            config.get('mysql.senha'),
                            {
                                host: config.get('mysql.host'),
                                dialect: 'mysql'
                            }
                        )
                        
                        module.exports = instancia
                        

Config

Modulo para isolar dados importantes em produção.

npm install config

Após a instalação do modulo escrever um objeto JSON contendo o objeto com dados de acesso a modo de ser expresso nas configurações do Sequelize.

                        {
                            "mysql":
                            {
                                "banco-de-dados": "nome",
                                "usuario": "root",
                                "senha": "123456",
                                "host": "127.0.0.1"
                            }
                        }
                        

Exportando Modulos

Utilize o comando module.exports = nome => {}
para exportar instale o modulo consign ele ira agrupar todas as rotas e colocar tudo dentro do app.

                            consign()
                            .include('pasta')
                            .into(app)
                        

Requisições

Podemos declarar no index principal mas por via de organização do código é prudente considerar colocar o comando em um arquivo separado.

Lembrar sempre de referenciar o comando no arquivo principal.
app.use('/caminho', função(requisicao, resposta){})

Em um novo arquivo:

    const roteador = require('express').Router()

    roteador.use('/', (requisicao, resposta) =>
    {
        resposta.send('connected')
    })

    module.exports = roteador
                    

Verbos HTTP

Retornar dados .get('/local', função)

Inserir dados no servidor.post('/local', função)

Alterar dados no servidor.path('/local', função)

Apagar dados no servidor.delete('/local', função)

.send('conteudo') envia dados.

Arquivo de Query

Comandos enviados para banco de dados em plataforma Query

Manipulando e Consultado BD

Após definir todos os arquivos e conectar todos ao app, é hora de configurar os arquivos que serão responsáveis pelas paginas da api. Se trata de um arquivo com Requisições agora de maneira estruturada criando a funcionalidade da api.

    const express = require('express')
    const router = express.Router()
    const mysql = require('../mysql').pool;
    
    router.get('/', (req, res, next) =>
    {
        mysql.getConnection((error, conn)=>
        {
            conn.query(
                'SELECT * FROM tabelax;',
                (error, result, fields)=>
                {
                    if(error) {return res.status(500).send({error: error})}
                    return res.status(200).send(result)
                })
        })
    });
    
    module.exports = router
                    
Com parametros
const express = require('express')
const router = express.Router()
const mysql = require('../mysql').pool;
    
router.get('/:id_produto', (req, res, next) => 
{
    mysql.getConnection((error, conn) => {
        conn.query(
            'SELECT * FROM produtos WHERE id_produto = ?;',
            [req.params.id_produto],
            (error, resultado, fields) => 
            {
                return res.status(200).send(resultado)
            }
            )
    })
})
module.exports = router
                    

Explicando o código, inicialmente declaramos todas as dependências que por via didática também é a ordem que usei para criar o projeto de exemplo.
Inicialmente pode se notar a clara estrutura de requisição, definindo caminho e função em um verbo ligado a estrutura.
Dentro da Arrow function temos então uma conexão e a mesma recebe parâmetros para a função, uma responsável por retornar um erro (não tratado para simplificar o exemplo) e outra que fornece uma conexão que abrigara nosso comando query.
Note que após declarar o comando query declaramos em um array o que deve conter no conteúdo "?".
Por fim declaramos uma nova arrow function, com a missão de responder a solicitação recebida.

Manipulando package.json

"scripts":

pode ser inserido scripts para trabalhar diretamente no terminal.

    ex:
                        "stripts": {
                        "start": "nodemon index.js",

                        "test": "echo \"Error: no test specified\...
                

O mesmo é invocado no terminal com o comando npm start

Facilitando comandos

nodemon

A biblioteca nodemon é uma boa alternativa para atualizar as alterações do servidor.
salve apenas em desenvolvimento --save-dev nodemon para restartar o servidor utilize o comando rs.

        configurando:
                        app.use(bodyParser.urlencoded({extended:true}))
                

moment

moment é biblioteca dedicada a trabalhar com datas, fazer calculos, manipular datas e formatar.

morgan

Após requisitar defina o app.use(morgan('dev')); o mesmo retornara um espelho da solicitação no terminal.

Comandos no terminal

Comando Função
node ./nome inicia documento
ctrl + c Derruba o servidor