Search code examples
javascriptnode.jsexpressejsmysql2

'req.body' return '{}' after validation of a <form> 'post' method with express


I am starting my end-of-year study project (due by mid-July :)). I'm trying to make a small site, and to stand out I'm not doing it in php but with node.js.

I discovered this technology and I am already facing a first problem. (After having trouble coding DB) I want to do an authentication but I am unable to retrieve the data from the <form>. When I do a log of my req.body.password, it returns undefined and for req.body, {}. I do not understand why.

Here is the code I already made:

index.js

require('dotenv').config();
const express = require("express");
const https = require("https");
const path = require("path");
const fs = require("fs");


const port = process.env.PORT || 4242;
const app = express();

// Analyser les corps de requête au format URL-encoded
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.set('views', './views');
app.set('view engine', 'ejs');

app.use('/', require('./controllers/homeController')); 

app.use('/images', express.static(path.join(__dirname, 'images')));

const sslServer = https.createServer({
    key: fs.readFileSync(path.join(__dirname, 'cert', 'key.pem')),
    cert: fs.readFileSync(path.join(__dirname, 'cert', 'cert.pem'))
}, app);
sslServer.listen(port, () => {
    console.log("Le serveur fonctionne !");
    console.log(process.env.PORT)
});

home.ejs

...
<main class="main">
   <div class="parent">
      <form method="post" class="enfant" id="loginForm">
         <input type="password" name="password" placeholder="password" id="pwd" required>
         <button type="submit" id="bouton">valider</button>
      </form>
   </div>
</main>
...
<script>
   document.getElementById("loginForm").addEventListener("submit", function(event) {
      event.preventDefault();
      const formData = new FormData(this);
      fetch('/', {
         method: "POST",
         body: formData
      })
      .then(response => {
         if (response.ok) {
            window.location.href = "/dashboard"; // Rediriger vers la page du tableau de bord si la connexion réussit
         } else {
            return response.text();
         }
      })
      .then(message => {
         document.getElementById("message").innerText = message;
         //alert(message);
      })
      .catch(error => {
         console.error('Error:', error);
      });
   });
</script>

User.js

const mysql = require("mysql2/promise");
require('dotenv').config();

class User {

  constructor(){
    this.dbConnect = mysql.createPool({
      host: process.env.DB_HOST,
      user: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME
    });
  }

  async get(){
    try{
      const connexion = await this.dbConnect.getConnection();
      const [res, fields] = await connexion.execute(`SELECT * FROM User;`);
      connexion.release();
      return await res;
    }
    catch(err){
      return await err;
    }
    finally{
      this.dbConnect.end();
    }
  }
}
module.exports = User;

homeController.js

const express = require('express');
const limiter = require('express-rate-limit');
const User = require('../models/User');

const app = express();
const homeRegex = /^\/(home)?$/;

// Middleware pour analyser les corps de requête
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

//limiter à 5 tentatives de log sur 5 minutes
const signInlimiter = limiter({ 
    windowMs: 5*60*1000, 
    limit: 1, 
    message: (req, res) => { 
        date = (new Date(req.rateLimit.resetTime)).toLocaleTimeString(); 
        return `Trop de tentatives ! Vous ne pourrez pas retenter avant ${date} ⏰.`; 
    },
    keyGenerator: (req, res) => {req.ip}
});

//REQUETES

app.get(homeRegex, (req, res) => { res.render("home.ejs", { message: "" }); });

// 429 par défaut
app.post(homeRegex, signInlimiter,  async (req, res) => {
    // Vérifier les informations de connexion et renvoyer une réponse appropriée (pour l'instant pwd = password)
    const password  = req.body.password;
    console.log(req.body)
    try {
        const userData = await getUser();
        const pwdData = userData[0].pwd;
        //non haché
        if (password === pwdData) {
            res.status(200).send("Bienvenue 💙🤍❤️");
        } else {
            res.status(401).send("Invalide 💀💀💀");
        }
    } catch (err) {
        
    }
});

async function getUser() {
    let user = new User();
    try {
        const userData = await user.get();
        return JSON.parse(JSON.stringify(userData, null, 2));
    } catch (err) {
        console.log(err);
        return null;
    }
}
module.exports = app;

I've already asked ChatGPT but obviously it's not all powerful ;b Can you explain to me why it doesn't work. Everything seems ok to me though (from my point of view, new to this tech).

Thanks.


Solution

  • With your answers I was able to modify the code so that everything works. Thanks.

    Here are the changes made:

    home.ejs

    <script>
       document.getElementById("loginForm").addEventListener("submit", function(event) {
          event.preventDefault();
          fetch("/", {
             method: "POST",
             body: JSON.stringify({
                //`this` = instance HTMLFormElement de l'élément <form>
                password: this.elements["password"].value,
             }),
             headers: {
                "Content-Type": "application/json"
             }
          })
          .then(response => {
             if (response.ok) {
                window.location.href = "/dashboard"; // Rediriger vers la page du tableau de bord si la connexion réussit
             } else {
                return response.text();
             }
          })
          .then(message => {
             document.getElementById("message").innerText = message;
             //alert(message);
          })
          .catch(error => {
             console.error('Error:', error);
          });
       });
    </script>