1. Objets Request et Response
Propriétés et méthodes de l'objet Request
L'objet Request (req
) dans Express représente la requête HTTP et possède de nombreuses propriétés et méthodes utiles pour accéder aux données envoyées par le client.
Propriétés principales
-
req.params : Contient les paramètres de route (parties de l'URL marquées par
:
)1// Route: /users/:userId 2// URL: /users/123 3console.log(req.params.userId); // "123"
-
req.query : Contient les paramètres de requête (après le
?
dans l'URL)1// URL: /search?q=express&limit=10 2console.log(req.query.q); // "express" 3console.log(req.query.limit); // "10"
-
req.body : Contient les données soumises dans le corps de la requête (nécessite un middleware comme
express.json()
ouexpress.urlencoded()
)1// POST avec JSON: { "name": "John", "age": 30 } 2console.log(req.body.name); // "John" 3console.log(req.body.age); // 30
-
req.headers : Contient les en-têtes HTTP de la requête
1console.log(req.headers['user-agent']); // Informations sur le navigateur 2console.log(req.headers.authorization); // En-tête d'autorisation
-
req.cookies : Contient les cookies envoyés par le client (nécessite le middleware
cookie-parser
)1console.log(req.cookies.sessionId); // Valeur du cookie "sessionId"
-
req.ip : Adresse IP du client
1console.log(req.ip); // "192.168.1.1"
-
req.path : Chemin de la requête
1// URL: /users/profile?sort=desc 2console.log(req.path); // "/users/profile"
-
req.protocol : Protocole de la requête ('http' ou 'https')
1console.log(req.protocol); // "http" ou "https"
-
req.secure : Boolean indiquant si la connexion est sécurisée (HTTPS)
1console.log(req.secure); // true pour HTTPS, false pour HTTP
-
req.method : Méthode HTTP de la requête
1console.log(req.method); // "GET", "POST", etc.
Méthodes utiles
-
req.get() : Récupère un en-tête HTTP spécifique
1console.log(req.get('Content-Type')); // "application/json"
-
req.is() : Vérifie le type de contenu de la requête
1if (req.is('json')) { 2 // Traitement pour JSON 3}
-
req.accepts() : Vérifie si le client accepte un type de contenu spécifique
1if (req.accepts('html')) { 2 res.send('<h1>Hello</h1>'); 3} else if (req.accepts('json')) { 4 res.json({ hello: 'world' }); 5}
Propriétés et méthodes de l'objet Response
L'objet Response (res
) représente la réponse HTTP qu'Express envoie au client.
Méthodes principales
-
res.send() : Envoie une réponse de n'importe quel type
1res.send('Hello World'); 2res.send({ name: 'John' }); 3res.send(Buffer.from('binary data'));
-
res.json() : Envoie une réponse JSON
1res.json({ user: 'John', id: 123 });
-
res.status() : Définit le code de statut HTTP
1res.status(404).send('Page non trouvée');
-
res.sendFile() : Envoie un fichier
1res.sendFile('/path/to/file.pdf');
-
res.render() : Rend un template avec des données
1res.render('profile', { user: 'John' });
-
res.redirect() : Redirige vers une autre URL
1res.redirect('/login'); 2res.redirect(301, 'https://example.com');
-
res.set() : Définit un en-tête HTTP
1res.set('Content-Type', 'text/plain'); 2res.set({ 3 'Content-Type': 'text/plain', 4 'X-Custom-Header': 'Custom Value' 5});
-
res.cookie() : Définit un cookie
1res.cookie('name', 'value', { maxAge: 900000, httpOnly: true });
-
res.clearCookie() : Supprime un cookie
1res.clearCookie('name');
-
res.download() : Invite à télécharger un fichier
1res.download('/path/to/file.pdf', 'rapport.pdf');
-
res.end() : Termine la réponse sans envoyer de données
1res.status(200).end();
-
res.format() : Répond différemment selon l'en-tête Accept
1res.format({ 2 'text/plain': () => { 3 res.send('Bonjour'); 4 }, 5 'text/html': () => { 6 res.send('<h1>Bonjour</h1>'); 7 }, 8 'application/json': () => { 9 res.json({ message: 'Bonjour' }); 10 }, 11 default: () => { 12 res.status(406).send('Not Acceptable'); 13 } 14});
Cycle de vie d'une requête-réponse
Le cycle de vie d'une requête-réponse dans Express suit ces étapes :
- Réception de la requête : Express reçoit la requête HTTP du client
- Traitement par les middlewares : La requête traverse les middlewares configurés
- Correspondance de route : Express trouve la route correspondante
- Exécution du gestionnaire de route : Le callback de la route est exécuté
- Génération de la réponse : Le gestionnaire génère une réponse
- Envoi de la réponse : La réponse est envoyée au client
Ce cycle peut être interrompu à tout moment si un middleware ou un gestionnaire de route :
- Envoie une réponse (avec
res.send()
,res.json()
, etc.) - Redirige la requête (avec
res.redirect()
) - Passe une erreur à
next()
2. Traitement des données entrantes
Paramètres d'URL
Les paramètres d'URL (ou paramètres de route) sont des segments variables dans l'URL, définis avec un préfixe :
dans la définition de la route.
1app.get('/users/:userId/posts/:postId', (req, res) => { 2 const { userId, postId } = req.params; 3 res.send(`Affichage du post ${postId} de l'utilisateur ${userId}`); 4});
Vous pouvez définir des contraintes sur les paramètres avec des expressions régulières :
1// Dans Express 4.x 2app.get('/users/:userId(\\d+)', (req, res) => { 3 // Ne correspond qu'aux IDs numériques 4 res.send(`Utilisateur ${req.params.userId}`); 5});
Query strings
Les query strings sont des paires clé-valeur ajoutées à la fin de l'URL après un point d'interrogation (?
).
1// URL: /search?q=express&sort=name&page=2 2app.get('/search', (req, res) => { 3 const { q, sort, page } = req.query; 4 5 // Valeurs par défaut et conversion de types 6 const searchTerm = q || ''; 7 const sortBy = sort || 'relevance'; 8 const pageNum = parseInt(page, 10) || 1; 9 10 res.send(`Recherche de "${searchTerm}", tri par ${sortBy}, page ${pageNum}`); 11});
Les query strings sont particulièrement utiles pour :
- Filtrage :
?category=books
- Tri :
?sort=price&order=desc
- Pagination :
?page=2&limit=10
- Recherche :
?q=express
Corps de requête (JSON, formulaires)
Pour traiter les données envoyées dans le corps de la requête, vous devez utiliser des middlewares appropriés :
1const express = require('express'); 2const app = express(); 3 4// Pour les données JSON 5app.use(express.json()); 6 7// Pour les données de formulaire 8app.use(express.urlencoded({ extended: true })); 9 10// Traitement d'une requête POST avec JSON 11app.post('/api/users', (req, res) => { 12 const { name, email, age } = req.body; 13 14 // Validation des données 15 if (!name || !email) { 16 return res.status(400).json({ error: 'Nom et email requis' }); 17 } 18 19 // Traitement des données... 20 21 res.status(201).json({ 22 message: 'Utilisateur créé', 23 user: { name, email, age } 24 }); 25}); 26 27// Traitement d'un formulaire 28app.post('/login', (req, res) => { 29 const { username, password } = req.body; 30 31 // Authentification... 32 33 res.redirect('/dashboard'); 34});
Pour des formulaires avec upload de fichiers, vous aurez besoin d'un middleware supplémentaire comme multer
:
1const multer = require('multer'); 2const upload = multer({ dest: 'uploads/' }); 3 4app.post('/profile', upload.single('avatar'), (req, res) => { 5 // req.file contient les informations sur le fichier uploadé 6 // req.body contient les autres champs du formulaire 7 res.send('Profil mis à jour'); 8});
Upload de fichiers
L'upload de fichiers nécessite généralement le middleware multer
:
1const express = require('express'); 2const multer = require('multer'); 3const path = require('path'); 4const app = express(); 5 6// Configuration de stockage 7const storage = multer.diskStorage({ 8 destination: (req, file, cb) => { 9 cb(null, 'uploads/'); // Dossier de destination 10 }, 11 filename: (req, file, cb) => { 12 // Génération d'un nom de fichier unique 13 const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); 14 cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); 15 } 16}); 17 18// Filtrage des fichiers 19const fileFilter = (req, file, cb) => { 20 // Accepter uniquement certains types de fichiers 21 if (file.mimetype.startsWith('image/')) { 22 cb(null, true); 23 } else { 24 cb(new Error('Seules les images sont autorisées'), false); 25 } 26}; 27 28// Initialisation de multer 29const upload = multer({ 30 storage: storage, 31 limits: { 32 fileSize: 5 * 1024 * 1024 // Limite à 5MB 33 }, 34 fileFilter: fileFilter 35}); 36 37// Upload d'un seul fichier 38app.post('/upload/profile', upload.single('avatar'), (req, res) => { 39 if (!req.file) { 40 return res.status(400).send('Aucun fichier uploadé'); 41 } 42 43 res.json({ 44 message: 'Fichier uploadé avec succès', 45 file: { 46 name: req.file.filename, 47 size: req.file.size, 48 mimetype: req.file.mimetype 49 } 50 }); 51}); 52 53// Upload de plusieurs fichiers 54app.post('/upload/gallery', upload.array('photos', 12), (req, res) => { 55 if (!req.files || req.files.length === 0) { 56 return res.status(400).send('Aucun fichier uploadé'); 57 } 58 59 res.json({ 60 message: `${req.files.length} fichiers uploadés avec succès`, 61 files: req.files.map(file => ({ 62 name: file.filename, 63 size: file.size, 64 mimetype: file.mimetype 65 })) 66 }); 67}); 68 69// Gestion des erreurs d'upload 70app.use((err, req, res, next) => { 71 if (err instanceof multer.MulterError) { 72 // Erreur Multer 73 return res.status(400).json({ 74 error: true, 75 message: err.message 76 }); 77 } else if (err) { 78 // Autre erreur 79 return res.status(500).json({ 80 error: true, 81 message: err.message 82 }); 83 } 84 next(); 85});
3. Formatage des réponses
Envoi de texte et HTML
Pour envoyer du texte brut ou du HTML, utilisez res.send()
:
1// Texte brut 2app.get('/text', (req, res) => { 3 res.set('Content-Type', 'text/plain'); 4 res.send('Ceci est du texte brut'); 5}); 6 7// HTML 8app.get('/html', (req, res) => { 9 res.send(` 10 <!DOCTYPE html> 11 <html> 12 <head> 13 <title>Page Express</title> 14 </head> 15 <body> 16 <h1>Bienvenue sur Express</h1> 17 <p>Ceci est une page HTML générée par Express</p> 18 </body> 19 </html> 20 `); 21});
Envoi de JSON
Pour envoyer des données JSON, utilisez res.json()
:
1app.get('/api/users', (req, res) => { 2 const users = [ 3 { id: 1, name: 'Alice', email: 'alice@example.com' }, 4 { id: 2, name: 'Bob', email: 'bob@example.com' } 5 ]; 6 7 res.json(users); 8}); 9 10app.get('/api/users/:id', (req, res) => { 11 const userId = parseInt(req.params.id, 10); 12 13 // Simuler une recherche en base de données 14 const user = { id: userId, name: 'Alice', email: 'alice@example.com' }; 15 16 if (user) { 17 res.json(user); 18 } else { 19 res.status(404).json({ error: 'Utilisateur non trouvé' }); 20 } 21});
res.json()
définit automatiquement le Content-Type
à application/json
et convertit les objets JavaScript en JSON.
Envoi de fichiers
Pour envoyer des fichiers, utilisez res.sendFile()
:
1const path = require('path'); 2 3app.get('/document', (req, res) => { 4 const filePath = path.join(__dirname, 'documents', 'rapport.pdf'); 5 6 res.sendFile(filePath, (err) => { 7 if (err) { 8 console.error('Erreur lors de l\'envoi du fichier:', err); 9 res.status(500).send('Erreur lors de l\'envoi du fichier'); 10 } 11 }); 12});
Pour forcer le téléchargement d'un fichier, utilisez res.download()
:
1app.get('/download/rapport', (req, res) => { 2 const filePath = path.join(__dirname, 'documents', 'rapport.pdf'); 3 4 res.download(filePath, 'rapport-annuel.pdf', (err) => { 5 if (err) { 6 console.error('Erreur lors du téléchargement:', err); 7 if (!res.headersSent) { 8 res.status(500).send('Erreur lors du téléchargement'); 9 } 10 } 11 }); 12});
Redirection
Pour rediriger vers une autre URL, utilisez res.redirect()
:
1// Redirection 302 (temporaire) par défaut 2app.get('/old-page', (req, res) => { 3 res.redirect('/new-page'); 4}); 5 6// Redirection 301 (permanente) 7app.get('/permanent-redirect', (req, res) => { 8 res.redirect(301, '/new-location'); 9}); 10 11// Redirection relative 12app.get('/products', (req, res) => { 13 res.redirect('categories'); // Redirige vers /products/categories 14}); 15 16// Redirection en arrière 17app.get('/cancel', (req, res) => { 18 res.redirect('back'); // Redirige vers la page précédente (Referer) 19});
Statuts HTTP
Il est important d'utiliser les codes de statut HTTP appropriés pour vos réponses :
1// 200 OK (par défaut pour res.send()) 2app.get('/success', (req, res) => { 3 res.status(200).send('Succès'); 4}); 5 6// 201 Created 7app.post('/api/resources', (req, res) => { 8 // Création d'une ressource... 9 res.status(201).json({ id: 123, message: 'Ressource créée' }); 10}); 11 12// 204 No Content 13app.delete('/api/resources/:id', (req, res) => { 14 // Suppression d'une ressource... 15 res.status(204).end(); 16}); 17 18// 400 Bad Request 19app.post('/api/validate', (req, res) => { 20 if (!req.body.email) { 21 return res.status(400).json({ error: 'Email requis' }); 22 } 23 res.json({ valid: true }); 24}); 25 26// 401 Unauthorized 27app.get('/api/protected', (req, res) => { 28 if (!req.headers.authorization) { 29 return res.status(401).json({ error: 'Authentification requise' }); 30 } 31 res.json({ data: 'Contenu protégé' }); 32}); 33 34// 403 Forbidden 35app.get('/api/admin', (req, res) => { 36 if (req.user && req.user.role !== 'admin') { 37 return res.status(403).json({ error: 'Accès interdit' }); 38 } 39 res.json({ data: 'Contenu administrateur' }); 40}); 41 42// 404 Not Found 43app.get('/api/resources/:id', (req, res) => { 44 const resource = findResourceById(req.params.id); 45 if (!resource) { 46 return res.status(404).json({ error: 'Ressource non trouvée' }); 47 } 48 res.json(resource); 49}); 50 51// 500 Internal Server Error 52app.get('/api/error', (req, res) => { 53 try { 54 // Opération qui peut échouer 55 throw new Error('Erreur interne'); 56 } catch (err) { 57 console.error(err); 58 res.status(500).json({ error: 'Erreur serveur' }); 59 } 60});
Exercices pratiques
Exercice 1 : Créer un formulaire et traiter sa soumission avec ExpressJS
Créez une application Express qui affiche un formulaire d'inscription et traite sa soumission. Le formulaire doit inclure des champs pour le nom, l'email et le mot de passe. Validez les données soumises et affichez un message de confirmation.
Exercice 2 : Implémenter un système d'upload de fichiers
Créez une application qui permet aux utilisateurs d'uploader des images. Limitez les types de fichiers acceptés aux images (JPEG, PNG, GIF) et la taille maximale à 5MB. Affichez les images uploadées dans une galerie.
Exercice 3 : Créer une API qui répond en différents formats
Créez une API qui peut renvoyer des données dans différents formats (JSON, XML, HTML) en fonction de l'en-tête Accept envoyé par le client. Utilisez res.format()
pour gérer les différents formats.