1

I am sending a POST request to my :8080 local host node.js server with my :3000 react.js application. And i get this CORS error in the browser. But I have enable the CORS in my back end node.js application. Here is the error:

Access to fetch at 'http://localhost:8080/feed/post' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. Feed.js:128 POST http://localhost:8080/feed/post net::ERR_FAILED 500 (Internal Server Error)

I have enable CORS in my back end application as given below and still get this error. I am using multipart form data with fetch in the front end. Any suggestion to solve this issue?

The server side back end code snippet in app.js

app.use(bodyParser.json()); // application/json
app.use(
  multer({ storage: fileStorage, fileFilter: fileFilter }).single("image")
);
app.use("/images", express.static(path.join(__dirname, "images")));

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "OPTIONS, GET, POST, PUT, PATCH, DELETE"
  );
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  next();
});

app.use("/feed", feedRoutes);
app.use("/auth", authRoutes);

app.use((error, req, res, next) => {
  console.log(error);
  const status = error.statusCode || 500;
  const message = error.message;
  const data = error.data;
  res.status(status).json({ message: message, data: data });
});

The serverside create post function

exports.createPost = (req, res, next) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    const error = new Error('Validation failed, entered data is incorrect.');

    const title = req.body.title;
  const content = req.body.content;
  console.log(title)
  console.log(content)
    error.statusCode = 422;
    throw error;
  }
  if (!req.file) {
    const error = new Error('No image provided.');
    error.statusCode = 422;
    throw error;
  }
 const imageUrl = req.file.path;
  const title = req.body.title;
  const content = req.body.content;
  const post = new Post({
    title: title,
    content: content,
    imageUrl: imageUrl,
    creator: { name: 'Maximilian' }
  });
  post
    .save()
    .then(result => {
      res.status(201).json({
        message: 'Post created successfully!',
        post: result
      });
    })
    .catch(err => {
      if (!err.statusCode) {
        err.statusCode = 500;
      }
      next(err);
    });
};

The front end react.js POST request code

finishEditHandler = postData => {
    this.setState({
      editLoading: true
    });
    const formData = new FormData();
    formData.append('title', postData.title);
    formData.append('content', postData.content);
    formData.append('image', postData.image);
    let url = 'http://localhost:8080/feed/post';
    let method = 'POST';
    if (this.state.editPost) {
      url = 'http://localhost:8080/feed/post/' + this.state.editPost._id;
      method = 'PUT';
    }

    fetch(url, {
      method: method,
      body: formData,
      headers: {
        Authorization: 'Bearer ' + this.props.token
      }
    })
      .then(res => {
        if (res.status !== 200 && res.status !== 201) {
          throw new Error('Creating or editing a post failed!');
        }
        return res.json();
      })
      .then(resData => {
        console.log(resData);
        const post = {
          _id: resData.post._id,
          title: resData.post.title,
          content: resData.post.content,
          creator: resData.post.creator,
          createdAt: resData.post.createdAt
        };
        this.setState(prevState => {
          let updatedPosts = [...prevState.posts];
          if (prevState.editPost) {
            const postIndex = prevState.posts.findIndex(
              p => p._id === prevState.editPost._id
            );
            updatedPosts[postIndex] = post;
          } else if (prevState.posts.length < 2) {
            updatedPosts = prevState.posts.concat(post);
          }
          return {
            posts: updatedPosts,
            isEditing: false,
            editPost: null,
            editLoading: false
          };
        });
      })
      .catch(err => {
        console.log(err);
        this.setState({
          isEditing: false,
          editPost: null,
          editLoading: false,
          error: err
        });
      });
  };
KileMax
  • 213
  • 2
  • 10
  • 2
    Is there some video or tutorial out that that literally everybody follows that says to write your own CORS middleware instead of using [cors()](https://github.com/expressjs/cors)?! What you have is an incomplete implementation. Don't re-invent the wheel – Phil Mar 28 '23 at 06:47
  • I don't recommend adding Multer's `single()` to every route. Use it only where required. See https://github.com/expressjs/multer#usage – Phil Mar 28 '23 at 06:48
  • @Phil what do recommend adding instead of Multer's single() route? Can this error occur due to that? Because I have tried almost every method inclusing using cors() to solve this. But still no positive result. – KileMax Mar 28 '23 at 16:13
  • 1
    Your request is failing with a HTTP 500 error (internal server error). CORS headers will not work if you error. – Evert Mar 28 '23 at 17:06
  • Nothing wrong with Multer's `single()`, just use it on the route you need it on instead of every route. Again, see the examples in the documentation – Phil Mar 28 '23 at 20:39
  • I have found the solution. The problem was not with the CORS though. But I will explain it here in case someone come across the same problem in future. The problem is with the 'fileStorage' variable. I have not mention it in the above code snippet. But earlier in the code i have define filename in the multer.diskStorage as (req, file, cb) => { cb(null, new Date().toISOString()+ '-' + file.originalname); but this will not applicable for Windows OS since it does not allow file names containing ':' – KileMax Mar 29 '23 at 09:45
  • And therefore use (req, file, cb) => { cb(null, new Date().toISOString().replace(/:/g, '-') + '-' + file.originalname); – KileMax Mar 29 '23 at 09:45
  • This will replace the ':' with '-' so it will applicable for Operating systems like Windows. – KileMax Mar 29 '23 at 09:47

0 Answers0