📚 Ressources — Node.js & Express

Cheatsheet complète de la formation — toutes les APIs, patterns et commandes essentiels en un coup d'œil.

⚙️ Node.js Core — Objets globaux

VariableDescription
processInfos processus, env vars, exit
process.env.XLire une variable d'environnement
process.argvArguments de la ligne de commande
process.exit(1)Arrêter le processus avec code
__dirnameRépertoire du fichier courant (absolu)
__filenameChemin complet du fichier courant
require('mod')Importer un module
module.exportsExporter depuis un module

📦 Modules natifs

Module / MéthodeUsage
fs.readFileSync(p, 'utf-8')Lire un fichier (synchrone)
fs.writeFileSync(p, data)Écrire un fichier (synchrone)
fs.existsSync(p)Vérifier qu'un fichier existe
path.join(__dirname, f)Chemin absolu robuste
path.resolve(rel)Résoudre un chemin relatif
path.extname('f.js')→ '.js'
http.createServer(cb)Serveur HTTP bas niveau
crypto.randomBytes(n)Bytes aléatoires sécurisés
os.cpus().lengthNombre de CPUs disponibles

📥 npm essentiels

CommandeDescription
npm init -yCréer package.json avec défauts
npm install pkgInstaller une dépendance
npm install -D pkgDépendance dev uniquement
npm installInstaller depuis package.json
npm run startLancer le script "start"
npm run devLancer le script "dev"
npx pkgExécuter sans installer globalement
^4.18.2Semver : compatible 4.x.x
~4.18.2Semver : compatible 4.18.x

🚀 Express — Setup & Routes

CodeDescription
const app = express()Créer l'application
app.use(express.json())Parser le body JSON
app.get(path, handler)Route GET
app.post(path, handler)Route POST
app.put(path, handler)Route PUT (remplacement)
app.patch(path, handler)Route PATCH (partiel)
app.delete(path, handler)Route DELETE
app.use(middleware)Middleware global
app.listen(port, cb)Démarrer le serveur

📩 Objet req

PropriétéContenu
req.params.idParamètre d'URL (:id)
req.query.pageQuery string (?page=2)
req.body.titreCorps de la requête (JSON)
req.headers['authorization']En-tête HTTP spécifique
req.method'GET', 'POST', etc.
req.path'/api/users'
req.ipIP du client
req.userDéfini par un middleware auth

📤 Objet res

MéthodeUsage
res.json(obj)Répondre en JSON (Content-Type auto)
res.status(404)Définir le status code (chaînable)
res.status(201).json(obj)Status + JSON en une ligne
res.send('texte')Répondre en texte brut
res.status(204).send()No Content (DELETE réussi)
res.redirect('/login')Redirection 302
res.setHeader('X', 'v')Définir un en-tête HTTP

🔧 Pattern Middleware

// Middleware standard (3 params)
function logger(req, res, next) {
  console.log(req.method, req.path);
  next(); // NE PAS oublier !
}

// Monter globalement
app.use(logger);

// Error handler (4 params OBLIGATOIRES)
app.use((err, req, res, next) => {
  res.status(err.status || 500)
     .json({ error: err.message });
});

// next(err) → propage l'erreur
app.get('/test', (req, res, next) => {
  next(new Error('Oups'));
});

🗺️ Router Express

// routes/articles.js
const router = express.Router();

// Chaînage sur même URL
router.route('/')
  .get((req, res) => { /*...*/ })
  .post((req, res) => { /*...*/ });

router.route('/:id')
  .get((req, res) => { /*...*/ })
  .put((req, res) => { /*...*/ })
  .delete((req, res) => { /*...*/ });

// Middleware de paramètre
router.param('id', (req, res, next, id) => {
  if (isNaN(+id)) return res.status(400).json({error:'ID invalide'});
  next();
});

module.exports = router;

// server.js
app.use('/articles', require('./routes/articles'));

🔐 JWT — jsonwebtoken

const jwt = require('jsonwebtoken');
const SECRET = process.env.JWT_SECRET;

// Créer un token
const token = jwt.sign(
  { id: user.id, role: user.role }, // payload
  SECRET,
  { expiresIn: '7d' }
);

// Vérifier un token
try {
  const payload = jwt.verify(token, SECRET);
  // payload.id, payload.role, payload.exp
} catch (err) {
  // TokenExpiredError ou JsonWebTokenError
}

// Middleware verifyToken
function verifyToken(req, res, next) {
  const header = req.headers.authorization;
  if (!header?.startsWith('Bearer '))
    return res.status(401).json({ error: 'Token manquant' });
  try {
    req.user = jwt.verify(header.slice(7), SECRET);
    next();
  } catch {
    res.status(401).json({ error: 'Token invalide' });
  }
}

// Header HTTP : Authorization: Bearer eyJhbG...

🔒 bcrypt — Hachage de mots de passe

const bcrypt = require('bcryptjs');

// Hacher (async — à faire au register)
const hash = await bcrypt.hash(password, 10);
// 10 = salt rounds (coût de calcul)
// Stocker `hash` en base, jamais `password`

// Vérifier (async — à faire au login)
const match = await bcrypt.compare(plainText, hash);
if (!match) return res.status(401).json({ error: 'Identifiants invalides' });

// NE JAMAIS :
// ✗ stocker des mots de passe en clair
// ✗ utiliser MD5/SHA1 pour les mots de passe
// ✗ comparer avec ===

📊 Status HTTP courants

CodeSignificationQuand ?
200OKGET/PUT/PATCH réussi
201CreatedPOST réussi (ressource créée)
204No ContentDELETE réussi (corps vide)
400Bad RequestChamps requis manquants
401UnauthorizedNon authentifié (token absent/invalide)
403ForbiddenAuthentifié mais pas autorisé
404Not FoundRessource introuvable
409ConflictEmail déjà utilisé, doublon
422UnprocessableDonnées sémantiquement invalides
500Server ErrorErreur interne imprévue

🛡️ Sécurité production

require('dotenv').config();
const helmet    = require('helmet');
const cors      = require('cors');
const rateLimit = require('express-rate-limit');

app.use(helmet());              // En-têtes HTTP sécurisés
app.use(cors({ origin: [...] })); // Whitelist origines
app.use(rateLimit({             // Anti-DDoS
  windowMs: 15 * 60 * 1000,
  max: 100
}));
app.use(express.json({ limit: '10kb' }));

// asyncHandler — plus de try/catch répétitifs
const asyncHandler = fn => (req, res, next) =>
  Promise.resolve(fn(req, res, next)).catch(next);

// Error handler production
app.use((err, req, res, next) => {
  const isDev = process.env.NODE_ENV !== 'production';
  res.status(err.status || 500).json({
    error: isDev ? err.message : 'Erreur serveur'
  });
});

🗄️ Pattern JsonDB — Persistance fichier

const fs = require('fs'), path = require('path');

class JsonDB {
  constructor(filename) {
    this.filepath = path.join(__dirname, filename);
    this.data = this._load();
  }
  _load() {
    try { return JSON.parse(fs.readFileSync(this.filepath, 'utf-8')); }
    catch { return {}; }
  }
  _save() { fs.writeFileSync(this.filepath, JSON.stringify(this.data, null, 2)); }
  getAll(key)        { return this.data[key] || []; }
  getById(key, id)   { return this.getAll(key).find(i => i.id === parseInt(id)); }
  insert(key, item) {
    const all = this.getAll(key);
    item.id = all.length ? Math.max(...all.map(i => i.id)) + 1 : 1;
    item.createdAt = new Date().toISOString();
    all.push(item); this.data[key] = all; this._save(); return item;
  }
  update(key, id, data) {
    const all = this.getAll(key);
    const idx = all.findIndex(i => i.id === parseInt(id));
    if (idx === -1) return null;
    all[idx] = { ...all[idx], ...data, id: parseInt(id) };
    this.data[key] = all; this._save(); return all[idx];
  }
  delete(key, id) {
    const all = this.getAll(key);
    const next = all.filter(i => i.id !== parseInt(id));
    if (next.length === all.length) return false;
    this.data[key] = next; this._save(); return true;
  }
}

module.exports = JsonDB;

✅ Bonnes pratiques Node.js & Express

Async / Erreurs

  • Toujours async/await plutôt que callbacks imbriqués
  • Entourer les I/O de try/catch
  • Utiliser asyncHandler pour chaque route async
  • Error handler 4-params en dernier middleware

Validation

  • Valider avant d'écrire en base
  • return res.status(400) stoppe l'exécution
  • Regex pour les emails : /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  • Extraire la validation dans un middleware

Sécurité

  • Ne jamais exposer le stack trace en production
  • Toujours hacher les mots de passe avec bcrypt
  • Utiliser process.env pour tous les secrets
  • Commiter .env.example, jamais .env

REST API

  • Status 201 pour POST, 204 pour DELETE réussi
  • Format uniforme { success, data }
  • Toujours paginer les listes (?page=&limit=)
  • Noms de routes au pluriel : /articles pas /article
← Accueil Formation