无法填充我的请求主体以测试Postman注册功能 *已修复*

huangapple go评论59阅读模式
英文:

Cannot populate my request body for testing signup functionality with Postman *FIXED*

问题

我正在开发一个非常基础的社交媒体应用程序,用户可以注册、登录、创建帖子、编辑他们的个人资料和帖子,删除帖子以及完全删除他们的帐户。

通过JWT创建并适当使用令牌,用户将上传所有相关文件到Cloudinary。个人资料图片存储在profile_pictures文件夹中,帖子存储在user_posts文件夹中。

所有这些在上周五测试时都正常工作。然而,现在,当我坐下来修复前端令牌时,我突然不能再注册用户了。所以我去了后端,检查了代码,然后去了Postman,测试了路由,但它不会填充请求体。

现在出现了更多问题,例如上传到Cloudinary的文件不再起作用,我不知道是否是由于他们最近的API更新引起的,尽管在他们的页面上写着“最后更新于6月15日”,而我上次注册和登录的测试是在6月16日星期五,这让我认为如果那时它工作,那么现在应该仍然可以工作。但它不起作用。

但这一切都不是我提出这个问题和寻求帮助的原因。我已经在我的应用程序中禁用了所有与文件上传相关的代码,只是为了测试将用户对象创建到MongoDB Atlas中。

这就是我的问题所在。由于我无法理解的原因,Postman将不会通过form-data填充任何内容,尽管一切似乎都是正确的,content-type也是正确的,要创建的用户对象的字段也是正确的。

只有当我在Postman中使用原始输入时,它才会填充它。我真的束手无策了...

如果有人知道这个问题的任何信息,我会非常感激您的帮助。

以下是相关的代码,请忽略已注释掉的与文件相关的代码行。

// 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

<details>
<summary>英文:</summary>

I am developing a very bare bones social media app, where users can signup, login, create posts, edit their profile and their posts, delete posts and delete themselves entirely.

Tokens via jwt should be created and used appropriately and users will upload all related files to cloudinary. Where profile pictures are stored in a profile_pictures folder and posts in a user_posts folder. 

All of this used to work when tested last friday. However now, out of nowhere when I sat down to fix the tokens on the frontend side, I suddenly couldn&#39;t signup a user anymore. So I went to the backend, checked the code, went to Postman, tested the route and it doesn&#39;t populate the request body.



Now there are more issues than that, for example the file upload to cloudinary is not working anymore either and I do not know if that is due to recent API updates on their end, even though on their page it says &quot;Last Updated 15th of June&quot; and my last signup and login tests were on friday the 16th of June, which makes me think that if it worked then it should still work now. But it doesn&#39;t.

All of that is not why I am posing this question and seeking aid, though. I have disabled all of the file upload related code in my app to just test the creation of a user object to mongo db atlas.

And here is where my problem lies. For some reason beyond my scope of knowledge and understanding Postman will not populate anything via form-data, even though everything is seemingly in order, the content-type is correct, the fields of the user object to be created are correct.

It will solely populate it if I use the raw input in Postman. And I am at my wits end here...

Please if anyone knows anything about this issue, I would be deeply grateful for your help.

Here is the related code, please ignore the commented out file related code lines.


// 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&amp;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&#39;t Connect to MongoDB Atlas!);
next(err);
}
}

Sorry if this is too much, but this is all the related code and I am losing my mind.
I know it is not wise to lay bare the ENVs but this is just an exercise for myself anyway therefore I have no qualms to share the ENVs.
I am very grateful for any and all input on this matter.
**UPDATE**:
I have fixed the issue of the request body not being populated with following code:
// In the auth route I imported multer:
const multer = require(&#39;multer&#39;)
const upload = multer()
// Then I added a method to the auth route before signup is called:
router.post(&#39;/signup&#39;, 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&#39;s the updated userModel profilePicture field:
profilePicture: { type: String, default: &#39;res.cloudinary.com/ddb2abwuu/image/upload/v1687256495/…&#39; } 
By doing these steps it now correctly populates the request body and I can create users again with Postman form-data and on the frontend, too.
The users can choose to change the default profilePicture with an upload of their own later through a patch route. Other websites handle user acquistion in a similar way.
Don&#39;t ask me why I have to do these mental gymnastics suddenly, when it all worked as it was just a few days ago but here we are.
I have a strong suspicion that at least one of the packages and dependencies I use have had some kind of API update that completely screwed me over.
As it stands this ticket is now solved. Hopefully this will be useful to anyone suffering from the same bizarre issue in the future.
</details>
# 答案1
**得分**: 0
截止目前,我已经找到了一个对我来说令人费解的解决方案:在我的`authRoute`中,我必须显式导入`multer`,然后创建:
```javascript
const multer = require('multer')
const upload = multer()

然后在auth路由中指定:

router.post('/signup', upload.none(), authController.signup)

我还放弃了在注册期间上传文件,并手动将默认个人资料图片添加到我的Cloudinary资产中,然后将其包含到我的用户模型中:

profilePicture: { type: String, default: 'res.cloudinary.com/ddb2abwuu/image/upload/v1687256495/…' }

像这样,注册和登录都可以正常工作。

通过执行这些步骤,现在正确填充了请求正文,我可以再次使用Postman的表单数据创建用户,并在前端上进行操作。

用户可以选择稍后通过patch路由更改默认个人资料图片。其他网站以类似的方式处理用户获取。

不要问我为什么突然要这样做,当几天前一切都正常工作时,但现在我们就在这里。

我强烈怀疑我使用的至少一个包和依赖项已经进行了某种API更新,完全搞乱了我的情况。

目前这个问题已经解决。希望对将来遇到同样奇怪问题的人有所帮助。

英文:

As of now I have found a solution which is mindboggling to me: In my authRoute I have to explicitly import multer then create

const multer = require(&#39;multer&#39;)
const upload = multer()

then in the auth route specify:

router.post(&#39;/signup&#39;, upload.none(), authController.signup)

I have also forfeited any file uploads during signup and just manually added a default profile picture to my cloudinary assets, which I included to my user model:

profilePicture: { type: String, default: &#39;res.cloudinary.com/ddb2abwuu/image/upload/v1687256495/…&#39; }

Like this both Signup and Login work again.

By doing these steps it now correctly populates the request body and I can create users again with Postman form-data and on the frontend, too.

The users can choose to change the default profilePicture with an upload of their own later through a patch route. Other websites handle user acquistion in a similar way.

Don't ask me why I have to do these mental gymnastics suddenly, when it all worked as it was just a few days ago but here we are.

I have a strong suspicion that at least one of the packages and dependencies I use have had some kind of API update that completely screwed me over.

As it stands this ticket is now solved. Hopefully this will be useful to anyone suffering from the same bizarre issue in the future.

huangapple
  • 本文由 发表于 2023年6月19日 19:42:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76506284.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定