
Créer une API REST avec Node.js et Express

Créer une API REST avec Node.js et Express
Dans ce tutoriel, nous allons créer une API REST complète avec Node.js et Express. Nous couvrirons la structure du projet, les routes, les contrôleurs, l'authentification et la validation des données.
Configuration initiale
Commençons par initialiser notre projet :
mkdir api-rest-express
cd api-rest-express
npm init -y
npm install express mongoose dotenv bcrypt jsonwebtoken joi cors helmet
npm install --save-dev nodemon
Structure du projet
/api-rest-express
/src
/config
db.js
/controllers
userController.js
productController.js
/middleware
auth.js
validate.js
/models
User.js
Product.js
/routes
userRoutes.js
productRoutes.js
/utils
errorHandler.js
app.js
.env
package.json
Connexion à la base de données
Créons notre fichier de configuration pour MongoDB :
// src/config/db.js
const mongoose = require('mongoose');
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log(`MongoDB Connected: ${conn.connection.host}`);
} catch (error) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
};
module.exports = connectDB;
Modèles
Créons nos modèles Mongoose :
// src/models/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true
},
password: {
type: String,
required: true,
minlength: 6
},
role: {
type: String,
enum: ['user', 'admin'],
default: 'user'
}
}, {
timestamps: true
});
// Hash le mot de passe avant de sauvegarder
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
// Méthode pour comparer les mots de passe
userSchema.methods.matchPassword = async function(enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
};
const User = mongoose.model('User', userSchema);
module.exports = User;
Middleware d'authentification
// src/middleware/auth.js
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const protect = async (req, res, next) => {
let token;
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
try {
// Extraire le token
token = req.headers.authorization.split(' ')[1];
// Vérifier le token
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// Ajouter l'utilisateur à la requête (sans le mot de passe)
req.user = await User.findById(decoded.id).select('-password');
next();
} catch (error) {
console.error(error);
res.status(401).json({ message: 'Non autorisé, token invalide' });
}
}
if (!token) {
res.status(401).json({ message: 'Non autorisé, pas de token' });
}
};
const admin = (req, res, next) => {
if (req.user && req.user.role === 'admin') {
next();
} else {
res.status(403).json({ message: 'Non autorisé, accès administrateur requis' });
}
};
module.exports = { protect, admin };
Routes et contrôleurs
// src/controllers/userController.js
const User = require('../models/User');
const jwt = require('jsonwebtoken');
// Générer un token JWT
const generateToken = (id) => {
return jwt.sign({ id }, process.env.JWT_SECRET, {
expiresIn: '30d'
});
};
// @desc Authentifier un utilisateur
// @route POST /api/users/login
// @access Public
const loginUser = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (user && (await user.matchPassword(password))) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user._id)
});
} else {
res.status(401).json({ message: 'Email ou mot de passe invalide' });
}
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// @desc Enregistrer un nouvel utilisateur
// @route POST /api/users
// @access Public
const registerUser = async (req, res) => {
try {
const { name, email, password } = req.body;
const userExists = await User.findOne({ email });
if (userExists) {
return res.status(400).json({ message: 'Utilisateur déjà existant' });
}
const user = await User.create({
name,
email,
password
});
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user._id)
});
} else {
res.status(400).json({ message: 'Données utilisateur invalides' });
}
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = { loginUser, registerUser };
Configuration de l'application Express
// src/app.js
const express = require('express');
const dotenv = require('dotenv');
const cors = require('cors');
const helmet = require('helmet');
const connectDB = require('./config/db');
const userRoutes = require('./routes/userRoutes');
dotenv.config();
// Connexion à la base de données
connectDB();
const app = express();
// Middleware
app.use(express.json());
app.use(cors());
app.use(helmet());
// Routes
app.use('/api/users', userRoutes);
// Route par défaut
app.get('/', (req, res) => {
res.send('API is running...');
});
// Gestion des erreurs 404
app.use((req, res) => {
res.status(404).json({ message: 'Route non trouvée' });
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Ce tutoriel vous a montré comment créer une API REST robuste avec Node.js et Express. Vous pouvez étendre cette base en ajoutant d'autres fonctionnalités comme la pagination, le filtrage, ou en intégrant des services tiers comme AWS S3 pour le stockage de fichiers.