So I’m new to programming and recently started learning Backend. Okay so recently I came across a problem with postman while making POST request. So when I wrote a controller for registering a user I used postman for testing and make a simple POST request with form-data which consist of fields like username, email, fullName, avatar, coverImage, password. And it worked perfectly fine and user got registered in the Database.
But when i did the same thing with my login controller like make a POST request with form-data which consist of fields username, password. It started throwing error like cannot read the properties of undefined. After some debugging I found out that the body in the request has an empty object and that’s why I’m getting this error. I tried sending Raw data from postman but that didn’t worked either, but finally when I tried with x-www-form-urlencoded it worked.
So my question is why does it worked with x-www-form-urlencoded and not with form-data and Raw? and also why was I getting an empty object while i was sending form-data and Raw data.
Here’s my registerUser controller –
const registerUser = asyncHandler( async (req, res) => {
const {fullName, email, username, password} = req.body
if ([fullName, email, username, password].some(field => field?.trim() === "")) { // we're using optional chaining to avoid running trim() on null or undefined field
throw new ApiError(400, "All fields are required!") // Checking if all the fields are non-empty
} else if (!email?.includes("@") || !email?.includes(".")) { // Checking if email is vaild or not
throw new ApiError(400, "Please enter a vaild email") // Its not a hard check for email
}
const existedUsername = await User.findOne({username})
const existedEmail = await User.findOne({username})
if (existedUsername) {
throw new ApiError(409, "Username already exist")
} else if (existedEmail) {
throw new ApiError(409, "Email is already linked to a different account")
}
let avatarLocalPath;
if (req.files && Array.isArray(req.files.avatar) && req.files.avatar.length > 0) {
avatarLocalPath = req.files?.avatar[0]?.path; // multer gives us the access of .files field in the request
}
let coverImageLocalPath; // manually checking if coverImage is provided or not before chaining
if (req.files && Array.isArray(req.files.coverImage) && req.files.coverImage.length > 0) {
coverImageLocalPath = req.files.coverImage[0].path;
}
if (!avatarLocalPath) {
throw new ApiError(400, "Avatar Local path is required!")
}
const avatar = await uploadOnCloudinary(avatarLocalPath);
// console.log(avatar)
const coverImage = await uploadOnCloudinary(coverImageLocalPath);
if (!avatar) {
throw new ApiError(400, "Avatar file is required")
}
const user = await User.create({
fullName,
avatar: avatar.url,
coverImage: coverImage?.url || "",
username: username.toLowerCase(),
email,
password,
})
const createdUser = await User.findById(user._id).select("-password -refreshToken");
if (!createdUser) {
throw new ApiError(500, "Something went wrong while registering the user")
}
return res.status(201).json(
new ApiResponse(200, createdUser, "User registered Successfully")
)
})
Here’s loginUser controller –
const loginUser = asyncHandler( async (req, res) => {
const {email, username, password} = req.body
if (!(username || email)) {
throw new ApiError(400, "Username or Email is required to Login")
}
const user = await User.findOne({
$or: [{username}, {email}]
})
if (!user) {
throw new ApiError(404, "User does not exist");
}
const isPasswordValid = await user.isPasswordCorrect(password);
if (!isPasswordValid) {
throw new ApiError(401, "Invaild user password");
}
const {accessToken, refreshToken} = await generateAccessAndRefreshTokens(user._id);
const loggedInUser = await User.findById(user._id).select("-password -refreshToken");
const options = {
httpOnly: true,
secure: true
}
return res
.status(200)
.cookie("accessToken", accessToken, options)
.cookie("refreshToken", refreshToken, options)
.json(new ApiResponse(
200,
{
user: loggedInUser,
accessToken,
refreshToken
},
"User logged In Successfully")
)
})