Ciao a tutti, appassionati di codice! Oggi voglio guidarvi attraverso un interessante progettino su cui ho lavorato: un’API per una Lista della Spesa realizzata con Express.js e MySQL.
Che tu sia uno sviluppatore esperto o un principiante alle prime armi, questo progetto offre spunti interessanti sulla semplicità e potenza dell’uso di Express accanto a un database MySQL.
Da dove partiamo: Express.js
Express è un framework web minimale e flessibile per Node.js, che offre un solido set di funzionalità (sarebbe troppo chiamarlo Framework) per applicazioni web e mobile. Uno dei suoi punti di forza è la semplicità nella creazione di API.
Configurazione e Dipendenze:
All’inizio del nostro codice, importiamo le librerie necessarie:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mysql = require('mysql');
const dotenv = require('dotenv');
Ecco una breve descrizione:
- express: Il framework principale.
- body-parser: Middleware per gestire i dati POST.
- cors: Middleware per abilitare la condivisione di risorse tra origini diverse, essenziale per molte applicazioni web.
- mysql: Driver Node.js per MySQL.
- dotenv: Per caricare le variabili di ambiente da un file
.env
.
Configurare l’Ambiente:
Utilizzando dotenv
, possiamo facilmente configurare le variabili di ambiente:
dotenv.config();
Questa linea carica le variabili da un file .env
, che potrebbe apparire così:
DB_HOST=tuo_host_database
DB_USER=tuo_utente_database
DB_PASSWORD=tua_password_database
DB_NAME=nome_tuo_database
Configurazione di Express:
La configurazione della nostra applicazione Express è di facile comprensione:
const app = express();
const port = 3000;
app.use(cors());
app.use(bodyParser.json());
Stiamo permettendo tutte le richieste CORS e analizzando i dati JSON in arrivo.
Inizializzazione del Database MySQL
MySQL è un affidabile e robusto sistema di database relazionali. Abbinarlo a Express è logico per molte applicazioni web. Ecco la configurazione del database:
const db = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
Dopo aver stabilito i parametri di configurazione della connessione dobbiamo assicurarci che questa sia correttamente stabilita:
db.connect(err => {
if (err) {
console.error('Errore di connessione al database:', err);
} else {
console.log('Connessione al database stabilita');
}
});
Lo SCHEMA del Database con DDL e DML (i dati di esempio)
La nostra API ruota attorno a una semplice tabella shopping_list, contenente un id, un item, e una quantity. Ecco la funzione che crea questa tabella se non esiste:
function createTableIfNotExists() {
const createTableQuery = `
CREATE TABLE IF NOT EXISTS shopping_list (
id INT AUTO_INCREMENT PRIMARY KEY,
item VARCHAR(255) NOT NULL,
quantity INT
)
`;
db.query(createTableQuery, (err, result) => {
if (err) {
console.error('Table creation error:', err);
} else {
console.log('Table creation successful');
insertSampleData();
}
});
}
Una vota creata la tabella vengono inserite 4 righe di esempio:
function insertSampleData() {
const sampleData = [
{ item: 'Eggs', quantity: 2 },
{ item: 'Bread', quantity: 1 },
{ item: 'Milk', quantity: 3 },
{ item: 'Cafe', quantity: 6 }
];
const insertQuery = 'INSERT INTO shopping_list (item, quantity) VALUES ?';
db.query(insertQuery, [sampleData.map(item => [item.item, item.quantity])], (err, result) => {
if (err) {
console.error('Error while inserting example data:', err);
} else {
console.log('Example data insertion success!');
}
});
}
Endpoint della API:
1. Recupero della Lista della Spesa:
app.get('/shopping-list', (req, res) => {
db.query('SELECT * FROM shopping_list', (err, result) => {
if (err) {
console.error(err);
res.status(500).send('Server error');
} else {
res.send(result);
}
});
});
Questo endpoint recupera tutta la lista della spesa restituendo un Array di oggetti JSON contenenti i dettagli dei singoli oggetti.
Un esempio di richiamo di questo endpoint potrebbe essere:
http://localhost:3000/shopping-list
2. Dettaglio di un Singolo Elemento della Lista:
// API to retrieve a single item from the shopping list
app.get('/shopping-list/:id', (req, res) => {
const itemId = req.params.id;
const query = 'SELECT * FROM shopping_list WHERE id = ?';
db.query(query, [itemId], (err, result) => {
if (err) {
console.error(err);
res.status(500).send('Server Error');
} else {
if (result.length > 0) {
res.send(result[0]);
} else {
res.status(404).send('Item not found');
}
}
});
});
Questo blocco di codice si occupa di recuperare un singolo oggetto all’interno del database utilizzando il suo “id”, un esempio di richiamo del end-point è questo:
http://localhost:3000/shopping-list/2
3. Eliminazione, Aggiornamento ed Inserimento
Per queste funzionalità avrete bisogno di un simulatore di richieste come “postman”, il codice non è direttamente accessibile dal browser perché quest’ultimo è in grado di effettuare solo delle chiamate GET.
// API for adding a new item to the shopping list
app.post('/shopping-list', (req, res) => {
const { item, quantity } = req.body;
const query = 'INSERT INTO shopping_list (item, quantity) VALUES (?, ?)';
db.query(query, [item, quantity], (err, result) => {
if (err) {
console.error(err);
res.status(500).send('Server error');
} else {
res.send('Item successfully added');
}
});
});
// API for updating an item existing in the shopping list
app.put('/shopping-list/:id', (req, res) => {
const itemId = req.params.id;
const { item, quantity } = req.body;
const query = 'UPDATE shopping_list SET item = ?, quantity = ? WHERE id = ?';
db.query(query, [item, quantity, itemId], (err, result) => {
if (err) {
console.error(err);
res.status(500).send('Server error');
} else {
res.send('Item successfully updated');
}
});
});
// API for deleting an element existing in the shopping list
app.delete('/shopping-list/:id', (req, res) => {
const itemId = req.params.id;
const query = 'DELETE FROM shopping_list WHERE id = ?';
db.query(query, [itemId], (err, result) => {
if (err) {
console.error(err);
res.status(500).send('Server error');
} else {
res.send('Item successfully deleted');
}
});
});
Avvio del server:
app.listen(port, () => {
console.log(`Server in esecuzione sulla porta ${port}`);
});
In questo blocco di codice si richiede l’avvio del server sulla porta selezionata.