skip to Main Content

I am developing a MERN stack web application which allows sellers to post their rooms on rent and for users to search and select the best room for them.

Whenever I execute the functionality Post Review the error "AxiosError {message: ‘Request failed with status code 500’, name: ‘AxiosError’, code: ‘ERR_BAD_RESPONSE‘," gets generated. What would be the issue in my code at backend or frontend when I submit the post at frontend.

I have used middleware such as isBuyer which allows only user which is a buyer to post a review for the room.

So here is my code :

FRONTEND CODE :

api.js (This is part of whole code where the backed apis are called)

import axios from 'axios';
const API_BASE_URL = 'http://localhost:5001/api/v1';
export const postReview = async (reviewData, id) => {
    try {
        const response = await axios.post(`${API_BASE_URL}/reviews/post-reviews/${id}`, reviewData, {
            withCredentials: true,
        });
        return response;
    } catch (error) {
        console.error('Error posting review:', error.response ? error.response.data : error.message);
        throw error;
    }
};

PostReview.jsx (Console gives error at line: 15)

import React, { useState } from 'react';
import { postReview } from '../api';

const PostReview = ({ id }) => {
  const [formData, setFormData] = useState({ rating: '', review: '' });
  const [error, setError] = useState(null);

  const handleChange = (e) => {
    setFormData({...formData, [e.target.name]: e.target.value });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const res = await postReview(formData, id);     /* --------- ERROR ---------- */
      console.log(res.data);
    }
    catch (error) {
      console.error('Error submitting review:', error);
      setError(error.response ? error.response.data.message : error.message);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          type="number"
          min={1}
          max={5}
          name="rating"
          value={formData.rating}
          placeholder='Rating'
          onChange={handleChange}
        />
        <input
          type="text"
          name="review"
          value={formData.review}
          placeholder='Review'
          onChange={handleChange}
        />
        <button type="submit">Post</button>
      </form>
      {error && <p>Error: {error}</p>}
    </div>
  );
};

export default PostReview;

SingleHostel.jsx (Here the PostReview component is used)

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { getSingleHostel } from '../api';
import PostReview from '../components/PostReview';
import { useUser } from '../context/userContext';

const SingleHostel = () => {
  const [room, setRoom] = useState([]);
  const { id } = useParams();
  const { user } = useUser();
  useEffect(() => {
    const fetchHostel = async () => {
      try {
        const res = await getSingleHostel(id);
        setRoom(res.data.hostel);
        console.log(res.data.hostel);
      } catch (error) {
        console.log(error.response ? error.response.data.message : error.message);
      }
    };
    fetchHostel();
  }, [id]);

  return (
    <div>
      <div>
        <h1>{room.name}</h1>
        <h1>{room.location}</h1>
        <h1>{room.address}</h1>
        <h1>{room.rent}</h1>
        <h1>{room.description}</h1>
        <h1>{room.status}</h1>
      </div>
      {user?.isBuyer ? <div> <PostReview id={room._id} /> </div> : null}
    </div>
  );
};

export default SingleHostel;

UserContext.jsx (React Context API form user data)

import React, { createContext, useContext, useState, useEffect } from 'react';
import { getCurrentUser as fetchCurrentUser } from '../api';

const UserContext = createContext();

export const useUser = () => {
  return useContext(UserContext);
};

export const UserProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        const userData = await fetchCurrentUser();
        setUser(userData);
      } catch (error) {
        console.error('Error fetching current user:', error.message);
      }
      setLoading(false);
    };

    fetchUser();
  }, []);

  return (
    <UserContext.Provider value={{ user, setUser, loading }}>
      {children}
    </UserContext.Provider>
  );
};

BACKEND CODE :

review.controllers.js

import {Review} from "../models/review.model.js";

const postReviews = async(req, res) => {
    try{
        const {id} = req.params;
        const {rating, comment} = req.body;
        if([rating, comment].some((data) => data.trim() === "")){
            return res.status(400).json({message: "Please fill all the fields."})
        }
        const review = await Review.create({user: req.user._id, hostel : id, rating, comment});
        res.status(201).json({message: "Review created successfully.", review})
    }
    catch(err){
        res.status(500).json({message: "Internal server error."})
    }
}

const getAllReviewsForHostel = async(req, res) => {
    try{
        const {id} = req.params;
        const reviews = await Review.find({hostel: id}).populate("user", "-password -refreshToken -isSeller -isBuyer");
        if(!reviews){
            return res.status(404).json({message: "No reviews found."})
        }
        res.status(200).json({message: "Reviews found successfully.", reviews})
    }
    catch(error){
        res.status(500).json({message: `Reviews fetching unsuccessfull. ERROR : ${error.message}`});
    }
}

export {postReviews, getAllReviewsForHostel};

userAuthmiddleware.js

import jwt from "jsonwebtoken";
import { User } from "../models/user.model.js";

const verifyUser = async (req, res, next) => {
    try {   
        const token = req.cookies?.accessToken;

        if(!token){
            return res.status(400).json({
                message : "Unauthorised Request! Token not found",
            })
        }

        const decodedToken = await jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);

        const user = await User.findById(decodedToken._id).select("-password -refreshToken");

        if(!user){
            return res.status(400).json({
                message : "Invalid decoded token",
            })
        }

        req.user = user;
        
        next();
    }
    catch (error){
        return res.status(400).json({
            message : `Invalid user. Authentication Failed ! ERROR : ${error.message}`,
        })
    }
}

export {verifyUser};

userIsBuyer middleware

import { User } from "../models/user.model.js";

const isBuyerAuth = async (req, res, next) => {
    try{
        const user = await User.findById(req.user.id);
        if(user.isBuyer){
            next();
        }
        else{
            return res.status(403).json({message: "You do not have access to this route."});
        }
    }
    catch(error){
        return res.status(500).json({message: `User buyer authentication error. ${error.message}`});
    }
}

export {isBuyerAuth};

Review.model.js

import mongoose from "mongoose";

const reviewSchema = new mongoose.Schema({  
    user : {
        type : mongoose.Schema.Types.ObjectId,
        ref : "User",
    },
    hostel : {
        type : mongoose.Schema.Types.ObjectId,
        ref : "Hostel",
    },
    rating : {
        type : Number,
        required : true,
        min : 1,
        max : 5,
    },
    comment : {
        type : String,
        required : true,
        maxLength : 500,
    },
    datePosted : {
        type : Date,
        default : Date.now,
    },
}, {timestamps : true});

export const Review = new mongoose.model("Review", reviewSchema);

review.routes.js

import {Router} from "express";
import { postReviews, getAllReviewsForHostel } from "../controllers/reviews.controllers.js";
import { isBuyerAuth } from "../middlewares/user.isBuyer.middleware.js";
import { verifyUser } from "../middlewares/user.auth.middleware.js";

const router = Router();

router.route("/post-reviews/:id").post(verifyUser, isBuyerAuth, postReviews);

router.route("/get-all-reviews/:id").get(verifyUser, getAllReviewsForHostel);


export default router;

app.js

import express from 'express';
import cors from 'cors';
import userRouter from './routes/user.routes.js';
import hostelRouter from './routes/hostel.routes.js';
import reviewRouter from './routes/review.routes.js';
import bookmarkRouter from './routes/bookmark.routes.js';
import cookieParser from 'cookie-parser';

const app = express();

const allowedOrigins = ['http://localhost:5174']; // Specify your frontend origin

const corsOptions = {
  origin: allowedOrigins,
  credentials: true, // This is required to allow cookies with CORS
};

app.use(cors(corsOptions));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

app.use('/api/v1/users', userRouter);
app.use('/api/v1/hostels', hostelRouter);
app.use('/api/v1/reviews', reviewRouter);
app.use('/api/v1/bookmarks', bookmarkRouter);

export default app;

I wanted to make sure that when user(Buyer) comes to the page of singleHostel he see the info of hostel and there is an option to post review for that hostel.

I tried testing the postReview using postman so there the review is getting posted successfully but when I try to do it with frontend form it givves me the error.

2

Answers


  1. Backend most probably.
    console.log the error in the backend in catch block to debug further.

    Login or Signup to reply.
  2. Some observations or comments:

    withCredentials: true

    It is necessary to give withCredentials: true with all of the requests to the backend since a cookie is in use in this app. From this question, it can be seen that it has been done so for the url /reviews/post-reviews/. Please see if it is given for all other requests from the frontend as well.

    A common mistake in this case is missing withCredentials: true with the signup request. It is required in this case as well. For an instance, please refer to this case Unable to access authorisation cookie
    enter link description here.

    The reason to discuss this point is that the way cookie is handled by the testing clients and standard Browsers varies.

    Use stack-trace

    To debug further, please use the stack-trace thrown by Express. This can be made displayed in the Browser console as below. The axios has the same in its response. For a minimal example, please see the answer in the post here Axios GET request to fetch tweets for specific user, returns 500 error, route not being reached.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search