Maison > Questions et réponses > le corps du texte
Je développe une application de médias sociaux très simple où les utilisateurs peuvent s'inscrire, se connecter, créer des publications, modifier leur profil et leurs publications, supprimer des publications et se supprimer complètement.
Les jetons via jwt doivent être créés et utilisés de manière appropriée et les utilisateurs téléchargent tous les fichiers pertinents sur cloudinary. Où les photos de profil sont stockées dans le dossier profile_pictures et les publications sont stockées dans le dossier user_posts.
Tout cela a fonctionné lors des tests vendredi dernier. Maintenant, cependant, alors que je m'assois pour réparer les jetons sur le frontend, tout d'un coup, je ne peux plus enregistrer d'utilisateurs. Je suis donc allé au backend, j'ai vérifié le code, je suis allé chez Postman, j'ai testé le routage et il ne remplissait pas le corps de la demande.
Plus de problèmes maintenant, par exemple, le téléchargement de fichiers sur cloudinary ne fonctionne plus non plus, je ne sais pas si cela est dû à la récente mise à jour de l'API, même si leur page indique "dernière mise à jour" le 15 juin », ma dernière inscription et connexion le test a eu lieu le vendredi 16 juin, ce qui m'a fait penser que si ça fonctionnait, ça devrait encore fonctionner maintenant. Mais ce n'est pas le cas
.Ce n’est pas pour cela que je pose cette question et que je demande de l’aide. J'ai désactivé tout le code lié au téléchargement de fichiers dans l'application pour tester la création d'objets utilisateur mongo db atlas.
C'est là que réside mon problème. Pour une raison qui dépasse mes connaissances et ma compréhension, Postman ne remplira rien avec les données du formulaire, même si tout semble être en ordre, que le type de contenu est correct et que les champs de l'objet utilisateur en cours de création sont corrects.
Si j'utilise une entrée brute dans Postman, cela le remplit simplement. Je suis à bout de nerfs...
Si quelqu'un connaît ce problème, j'apprécierais vraiment votre aide.
Ce qui suit est le code pertinent, veuillez ignorer les lignes de code commentées liées au fichier.
// AUTH CONTROLLER: // controller for user signup module.exports.signup = async (req, res, next) => { try { console.log(req.body, "req body"); // retrieve user from db by email provided in request body const foundUser = await User.findOne({ email: req.body.email }); console.log(foundUser, "found user"); // check if foundUser already exists in db if (foundUser) { res.status(409).json({ message: `Email already in use. Please choose another.` }); } // generate salt and hash for the user password const salt = bcrypt.genSaltSync(Number(process.env.SALT_ROUND)); const hash = bcrypt.hashSync(req.body.password, salt); // create a new user object from user model const newUser = new User({ username: req.body.username, name: req.body.name, email: req.body.email, password: hash, //profilePicture: req.file.path }); // console.log(req.file, "req file"); await newUser.save(); // save the new user object to the database // upload the profile picture to cloudinary storage // const result = await cloudinary.uploader.upload(req.file.path, { // public_id: `profile_pictures/${newUser._id}`, // }); //newUser.profilePicture = result.secure_url; //await newUser.save(); // update newUser with the profilePicture URL console.log(newUser, "new user"); // generate a signup token // const token = jwt.sign({ newUserId: newUser._id, newUserName: newUser.username, newUserProfilePicture: newUser.profilePicture }, process.env.JWT_SECRET, { // expiresIn: '5m' // expires in 5 minutes (in case signup was erroneous) // }); // store the token as a cookie // res.cookie('jwt', token, { // httpOnly: true // }); // respond with the newly created user object and the created token res.status(201).json({ message: `User created successfully!`, user: newUser }); } catch (err) { next(err); }; };
// AUTH ROUTE: // import dependencies const express = require('express') const authController = require('../controllers/authController') //const authHandler = require('../middlewares/authHandler') // create new router object const router = express.Router() // import controllers router.post('/signup', authController.signup) //router.post('/login', authController.login) //router.get('/logout', authHandler.checkUser, authController.logout) module.exports = router
// USER MODEL: const mongoose = require("mongoose") const bcrypt = require("bcrypt") const UserSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, password: { type: String, required: true }, name: { type: String, required: true }, username: { type: String, unique: true }, //profilePicture: { type: String }, }) // usually you hash/salt inside the appropriate model; like our userModel here. // // but we save the user-object twice for following two reasons: // - the regular data of the user-object gets saved to our mongoDB atlas database. // - and the profile picture gets uploaded and saved in an appropriate folder to cloudinary. // // this triggers the password hash twice, which in return falsifies the user password on login attempt. // therefore we ignore the code snippet below and directly salt and hash in our authController. // // hash and salt user password before saving to database // UserSchema.pre("save", async function (next) { // const salt = await bcrypt.genSalt(); // this.password = await bcrypt.hash(this.password, salt); // next(); // }); // pre-hook for updating password field UserSchema.pre('findOneAndUpdate', function (next) { const update = this.getUpdate() if (update.password) { bcrypt.hash(update.password, Number(process.env.SALT_ROUND), function (err, hash) { if (err) return next(err) update.password = hash next() }) } }) // compare the password entered by the user with the hashed password in the database UserSchema.methods.comparePassword = function (candidatePassword, cb) { bcrypt.compare(candidatePassword, this.password, function (err, isMatch) { if (err) return cb(err) //cb(err) passes errors down to error handler the same way next(err) does cb(null, isMatch) }) } const User = mongoose.model("User", UserSchema) module.exports = User
// SERVER: // import dependencies const cors = require('cors'); const express = require('express'); const cookieParser = require('cookie-parser'); // import routes (modules) const authRoute = require('./routes/authRoute'); const userRoute = require('./routes/userRoute'); const postRoute = require('./routes/postRoute'); const app = express(); // initialize express // import middlewares const { connectMongoDB } = require('./lib/mongoose'); // destruct mongoDB connector const { errorHandler } = require('./middlewares/errorHandler'); // destruct errorHandler // allow requests from specified origins with specific methods const whitelist = [process.env.FRONTEND_URL, 'https://www.arii.me']; // add cors options const corsOptions = { origin: (origin, callback) => { if (whitelist.indexOf(origin) !== -1 || !origin) { callback(null, true); } else { callback(new Error('CORS issues')); }; }, credentials: true, }; // enable cross-origin resource sharing with specified options for the express app app.use(cors(corsOptions)); // parse incoming cookies and make them accessible in req.cookies app.use(cookieParser()); // enable parsing of incoming JSON data in the request body by the express app app.use(express.json()); app.use(express.urlencoded({ extended: false })); // define routes app.use('/auth', authRoute); app.use('/users', userRoute); app.use('/posts', postRoute); // define middlewares connectMongoDB(); app.use(errorHandler); // error handler must be last invoked middleware // listen to server app.listen(process.env.PORT || 3003, () => { console.log(`Server up and running at ${process.env.PORT}`); });
// MONGOOSE: // import dependencies const mongoose = require('mongoose'); require('dotenv').config(); // destruct envs const { DB_USER, DB_PASS, DB_HOST, DB_NAME } = process.env; // atlas connection string const mongoURI = `mongodb+srv://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_NAME}?retryWrites=true&w=majority`; // middleware function for handling connections to the mongoDB atlas database module.exports.connectMongoDB = async () =>{ try { await mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true, }); console.log(`Connected to MongoDB Atlas!`); } catch (err) { console.log(`Couldn't Connect to MongoDB Atlas!`); next(err); } }
Désolé si c'est trop, mais c'est tout le code pertinent et j'ai perdu la tête. Je sais que ce n'est pas sage de divulguer ENV, mais ce n'est qu'un exercice pour moi, donc je n'ai aucun scrupule à partager ENV.
J'apprécie vraiment toutes les opinions sur ce sujet.
Mise à jour :
J'ai résolu le problème où le corps de la requête n'était pas renseigné avec le code suivant :
// In the auth route I imported multer: const multer = require('multer') const upload = multer() // Then I added a method to the auth route before signup is called: router.post('/signup', upload.none(), authController.signup) // I have also forfeited any file upload during signup // and replaced them with a default image in my cloudinary assets. // Here's the updated userModel profilePicture field: profilePicture: { type: String, default: 'res.cloudinary.com/ddb2abwuu/image/upload/v1687256495/…' }
En suivant ces étapes, le corps de la requête est désormais correctement rempli et je peux également utiliser les données du formulaire Postman et créer à nouveau l'utilisateur sur le frontend.
Les utilisateurs peuvent choisir de modifier la photo de profil par défaut ultérieurement en téléchargeant leur propre profil via patcher. D'autres sites Web gèrent l'acquisition d'utilisateurs de la même manière.
Ne me demandez pas pourquoi je dois subitement faire cette gymnastique mentale, même si tout fonctionne aussi bien qu’il y a quelques jours, nous y sommes.
Je soupçonne fortement qu'au moins un des packages et dépendances que j'utilise avait une sorte de mise à jour de l'API qui m'a complètement gâché.
Pour l'instant, ce ticket est désormais résolu. J'espère que cela sera utile à tous ceux qui rencontreront le même problème étrange à l'avenir.
P粉0215534602024-04-02 09:20:01
Jusqu'à présent, j'ai trouvé une solution à laquelle je n'arrive pas à croire : dans mon authRoute, je dois explicitement importer multer puis créer
const multer = require('multer') const upload = multer()
Puis précisez dans le parcours d'authentification :
router.post('/signup', upload.none(), authController.signup)
J'ai également abandonné tout téléchargement de fichiers lors de l'inscription et j'ai simplement ajouté manuellement la photo de profil par défaut à mes actifs cloudinaires et je l'ai ajoutée à mon modèle d'utilisateur :
profilePicture: { type: String, default: 'res.cloudinary.com/ddb2abwuu/image/upload/v1687256495/…' }
L'inscription et la connexion fonctionneront donc à nouveau.
En suivant ces étapes, le corps de la requête est désormais correctement rempli et je peux également utiliser les données du formulaire Postman et créer à nouveau l'utilisateur sur le frontend.
Les utilisateurs peuvent choisir de modifier la photo de profil par défaut ultérieurement en téléchargeant leur propre profil via patcher. D'autres sites Web gèrent l'acquisition d'utilisateurs de la même manière.
Ne me demandez pas pourquoi je dois subitement faire cette gymnastique mentale, même si tout fonctionne aussi bien qu’il y a quelques jours, nous y sommes.
Je soupçonne fortement qu'au moins un des packages et dépendances que j'utilise avait une sorte de mise à jour de l'API qui m'a complètement gâché.
À partir de maintenant, ce problème est désormais résolu. J'espère que cela sera utile à tous ceux qui rencontreront le même problème étrange à l'avenir.