TW3 — Technologies du Web 3

Exercice — API Express + MongoDB

Développez une petite API Express connectée à MongoDB, testée avec une instance MongoDB lancée via Docker.

Objectif : construire une mini API REST CRUD avec Express et MongoDB. Ici, Docker sert à lancer le serveur MongoDB ; l'application Node.js, elle, tourne localement pendant l'exercice.

Le projet : node-mongodb-docker

Structure attendue :

node-mongodb-docker/
  src/
    index.js
    public/
      index.html
      style.css
      script.js
  package.json

Le front envoie des données vers quatre routes :

  • POST /addData pour créer un document,
  • GET /list pour lister les documents,
  • PUT /updateData/:id pour modifier un document,
  • DELETE /deleteData/:id pour supprimer un document.

Étapes pas à pas

1. Démarrer MongoDB

Via Docker : docker run -d -p 27017:27017 --name mongo mongo:7.

2. Installer les dépendances

npm install express mongodb body-parser

3. Coder le serveur

Utilisez MongoClient pour gérer la connexion, puis implémentez les routes de création, lecture, mise à jour et suppression.

4. Tester le front

Faites dialoguer public/index.html + script.js avec l'API, puis testez les routes avec le navigateur ou curl.

Le serveur complet

const express = require("express")
const { MongoClient, ObjectId } = require("mongodb")
const bodyParser = require("body-parser")

const app = express()
const PORT = process.env.PORT || 3000
const mongoUrl = "mongodb://localhost:27017"

app.use(bodyParser.json())
app.use(express.static("src/public"))

app.post("/addData", async (req, res) => {
  let client

  try {
    client = new MongoClient(mongoUrl)
    await client.connect()

    const collection = client.db("test").collection("ma_collection")
    const result = await collection.insertOne({ content: req.body.data })

    res.json({ message: "Data added successfully", id: result.insertedId })
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" })
  } finally {
    if (client) {
      await client.close()
    }
  }
})

app.get("/list", async (req, res) => {
  let client

  try {
    client = new MongoClient(mongoUrl)
    await client.connect()

    const collection = client.db("test").collection("ma_collection")
    const list = await collection.find().toArray()

    res.json({ list })
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" })
  } finally {
    if (client) {
      await client.close()
    }
  }
})

app.put("/updateData/:id", async (req, res) => {
  let client

  try {
    client = new MongoClient(mongoUrl)
    await client.connect()

    const collection = client.db("test").collection("ma_collection")
    const result = await collection.updateOne(
      { _id: new ObjectId(req.params.id) },
      { $set: { content: req.body.data } }
    )

    if (result.matchedCount === 0) {
      return res.status(404).json({ error: "Document not found" })
    }

    res.json({ message: "Data updated successfully" })
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" })
  } finally {
    if (client) {
      await client.close()
    }
  }
})

app.delete("/deleteData/:id", async (req, res) => {
  let client

  try {
    client = new MongoClient(mongoUrl)
    await client.connect()

    const collection = client.db("test").collection("ma_collection")
    const result = await collection.deleteOne({ _id: new ObjectId(req.params.id) })

    if (result.deletedCount === 0) {
      return res.status(404).json({ error: "Document not found" })
    }

    res.json({ message: "Data deleted successfully" })
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" })
  } finally {
    if (client) {
      await client.close()
    }
  }
})

app.listen(PORT, () => console.log(`App listening on port ${PORT}`))

Conseils

  • Gardez une seule base et une seule collection cohérentes entre toutes les routes.
  • express.static("src/public") sert le front.
  • Conservez l'identifiant _id renvoyé par POST /addData pour tester ensuite PUT et DELETE.

⚠️ Pièges à éviter

Collection différente entre écriture et lecture : si /addData écrit dans data et /list lit ma_collection, la liste sera vide. Uniformisez.

Mongo non démarré : MongoClient échouera si le conteneur est arrêté. Vérifiez docker ps et le port 27017.

Connexion laissée ouverte : appelez client.close() dans le finally pour ne pas épuiser les connexions.

Identifiant invalide : une route PUT ou DELETE avec un mauvais _id ne retrouvera aucun document.

Critères de réussite

  • MongoDB lancé via Docker.
  • POST /addData insère un document.
  • GET /list renvoie les documents insérés.
  • PUT /updateData/:id modifie un document existant.
  • DELETE /deleteData/:id supprime un document existant.

Pour aller plus loin

Relisez Modélisation et CRUD avant le quiz.

MongoDB

Terminez le quiz du chapitre pour le marquer comme complété.

Tableau de bord

On this page