Express Router e organizzazione
Prima di iniziare: le parole della lezione
- Router e prefisso
- Un Router è un insieme componibile di route e middleware. Il prefisso di montaggio collega quel gruppo a una parte dell’URL dell’app.
- Controller, service e repository
- Il controller gestisce ingresso e risposta HTTP; il service applica regole del dominio; il repository legge e scrive i dati. Sono ruoli organizzativi, non oggetti creati automaticamente da Express.
- MVC
- Model–View–Controller: separa modello e dati, presentazione e gestione dell’interazione. In un’API JSON la presentazione non è necessariamente una pagina HTML.
Con l'aumentare delle route conviene separarle dal file principale. express.Router() consente di raggruppare endpoint e middleware.
// routes/persone.cjs
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => res.json([{ id: 1, nome: 'Anna' }]));
router.get('/:id', (req, res) => res.json({ id: Number(req.params.id) }));
module.exports = router;
// server.cjs
const express = require('express');
const personeRouter = require('./routes/persone.cjs');
const app = express();
app.use('/api/persone', personeRouter);
app.listen(3000);
Esempio aggiuntivo: un futuro progetto può dividere codice in routes/, controllers/, services/ e repositories/. Il video finale accenna a sviluppi successivi (MVC e database), ma queste parti non sono spiegate nel materiale introduttivo fornito.
Chi fa cosa, e perché
app.use("/api/persone", personeRouter) affida al router le richieste sotto quel prefisso. All’interno scrivi router.get("/") e router.get("/:id"). Ripetere /api/persone dentro il router produrrebbe un percorso duplicato. Per una richiesta al router, req.originalUrl conserva l’URL originale, mentre Express gestisce il percorso relativo al montaggio.
La catena completa può essere: server → parser e middleware → router → controller → service → repository → risposta. Il router sceglie chi gestisce la richiesta; non è lui, da solo, a rendere persistenti i dati. Parti da pochi file con responsabilità chiare e separali quando questo rende il flusso più comprensibile.
Un altro esempio guidato
// controllers/salute.cjs
function leggiSalute(req, res) {
res.json({ ok: true });
}
module.exports = { leggiSalute };
// routes/salute.cjs — secondo file
const router = require('express').Router();
const { leggiSalute } = require('../controllers/salute.cjs');
router.get('/', leggiSalute);
module.exports = router;
// server.cjs — aggiunta prima di listen e della 404
// app.use('/api/salute', require('./routes/salute.cjs'));
Come leggerlo e risultato atteso. Crea le due cartelle e i due file separati. Nel server già configurato aggiungi la riga app.use togliendo //. GET /api/salute viene selezionata dal router e la risposta è costruita dal controller. Non chiamare leggiSalute() mentre registri la route: passa il riferimento alla funzione.
Prova tu. Sposta le route CRUD nel router persone e controlla che gli URL pubblici restino identici. Poi indica in quale file metteresti una regola “nome non vuoto” e in quale una query di lettura.