Creer une API REST avec Node.js et Express

Credit : Illustration backtotheweb.fr

Creer une API REST avec Node.js et Express

Dylan D. — Agent Support Technique Serveur Web 655 mots 4 min

Initialiser le projet

Creez un projet Node.js avec la structure suivante :

mkdir mon-api && cd mon-api
npm init -y
npm install express mongoose jsonwebtoken bcryptjs joi dotenv cors helmet
npm install -D nodemon

Ajoutez le script de developpement dans package.json :

"scripts": {
    "dev": "nodemon src/index.js",
    "start": "node src/index.js"
}

Point d'entree et middleware

Creez src/index.js :

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const helmet = require('helmet');
require('dotenv').config();

const app = express();

// Middleware globaux
app.use(helmet());              // Headers de securite
app.use(cors());                // Cross-Origin
app.use(express.json());        // Parser JSON
app.use(express.urlencoded({ extended: true }));

// Connexion MongoDB
mongoose.connect(process.env.MONGO_URI)
    .then(() => console.log('MongoDB connecte'))
    .catch(err => console.error('Erreur MongoDB:', err));

// Routes
app.use('/api/auth', require('./routes/auth'));
app.use('/api/articles', require('./routes/articles'));

// Gestion d'erreurs globale
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(err.status || 500).json({
        error: err.message || 'Erreur interne du serveur'
    });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`API demarree sur le port ${PORT}`));

Creer une API REST avec Node.js et Express

Modele Mongoose

Creez src/models/Article.js :

const mongoose = require('mongoose');

const articleSchema = new mongoose.Schema({
    title:   { type: String, required: true, trim: true },
    content: { type: String, required: true },
    author:  { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
    tags:    [String],
    status:  { type: String, enum: ['draft', 'published'], default: 'draft' }
}, { timestamps: true });

articleSchema.index({ title: 'text', content: 'text' });

module.exports = mongoose.model('Article', articleSchema);

Validation avec Joi

Creez src/validators/article.js :

const Joi = require('joi');

const articleValidator = (req, res, next) => {
    const schema = Joi.object({
        title: Joi.string().min(3).max(200).required(),
        content: Joi.string().min(10).required(),
        tags: Joi.array().items(Joi.string().max(30)).max(10),
        status: Joi.string().valid('draft', 'published')
    });

    const { error } = schema.validate(req.body);
    if (error) {
        return res.status(400).json({ error: error.details[0].message });
    }
    next();
};

module.exports = articleValidator;

Creer une API REST avec Node.js et Express

Authentification JWT

Creez src/middleware/auth.js :

Astuce : j'ai appris ça à la dure après un incident en prod un vendredi soir.

const jwt = require('jsonwebtoken');

const auth = (req, res, next) => {
    const header = req.header('Authorization');
    if (!header || !header.startsWith('Bearer ')) {
        return res.status(401).json({ error: 'Token manquant' });
    }

    try {
        const token = header.replace('Bearer ', '');
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        req.user = decoded;
        next();
    } catch (err) {
        res.status(401).json({ error: 'Token invalide' });
    }
};

module.exports = auth;

Routes CRUD

Creez src/routes/articles.js :

const router = require('express').Router();
const Article = require('../models/Article');
const auth = require('../middleware/auth');
const validate = require('../validators/article');

// GET /api/articles - Liste avec pagination
router.get('/', async (req, res) => {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 10;
    const skip = (page - 1) * limit;

    const [articles, total] = await Promise.all([
        Article.find({ status: 'published' })
            .populate('author', 'name')
            .sort({ createdAt: -1 })
            .skip(skip)
            .limit(limit),
        Article.countDocuments({ status: 'published' })
    ]);

    res.json({ articles, page, totalPages: Math.ceil(total / limit), total });
});

// GET /api/articles/:id
router.get('/:id', async (req, res) => {
    const article = await Article.findById(req.params.id).populate('author', 'name');
    if (!article) return res.status(404).json({ error: 'Article non trouve' });
    res.json(article);
});

// POST /api/articles - Creer (authentifie)
router.post('/', auth, validate, async (req, res) => {
    const article = new Article({ ...req.body, author: req.user.id });
    await article.save();
    res.status(201).json(article);
});

// PUT /api/articles/:id - Modifier
router.put('/:id', auth, validate, async (req, res) => {
    const article = await Article.findOneAndUpdate(
        { _id: req.params.id, author: req.user.id },
        req.body,
        { new: true, runValidators: true }
    );
    if (!article) return res.status(404).json({ error: 'Article non trouve' });
    res.json(article);
});

// DELETE /api/articles/:id
router.delete('/:id', auth, async (req, res) => {
    const article = await Article.findOneAndDelete({ _id: req.params.id, author: req.user.id });
    if (!article) return res.status(404).json({ error: 'Article non trouve' });
    res.json({ message: 'Article supprime' });
});

module.exports = router;

Deployer sur votre serveur IONOS

Utilisez PM2 pour gerer le processus :

npm install -g pm2
pm2 start src/index.js --name mon-api
pm2 save
pm2 startup

Votre API REST est prete, avec authentification JWT, validation des donnees et pagination.

# Articles similaires

// newsletter

Cet article vous a aide ? Recevez les prochains par email.