Codecygen
Codecygen

Reputation: 121

Simple Fetch API Post Request Fails No Matter What

I have been working on this issue for 2 days, looked at various pages and cannot find a single solution that would work.

Please only reply if you know how to write them with async await functions and please reply if you know the answer of fetch api. I am not looking for axios solutions for the time being. I have a backend server which runs on port 8000 of localhost, frontend runs on port 3000. Front end is written in React, backend is written in Node/Express.

I am able to successfully make a GET request from backend server but the POST request fails for some reason with the error "VM942:1 POST http://localhost:8000/frontend-to-backend 500 (Internal Server Error)"

Backend server has this error: SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse ()

  // React-To-Node-Connection
  // React "App.js" file
  // "package.json" file contains this
  // "proxy": "http://localhost:8000"
  useEffect(() => {
    const getBackend = async () => {
      const res = await fetch('backend-to-frontend');
      const data = await res.json();

      if (!res.ok) {
        throw new Error(`Cannot get data from backend server. HTTP Status: ${res.status}`);
      }

      console.log(data.message);
      // Prints "Hi from backend!"
    }

    getBackend();

    const postBackend = async () => {

      try {
        const res = await fetch('http://localhost:8000/frontend-to-backend',
          {
            method: 'POST',
            mode: 'no-cors',
            body: JSON.stringify({ message: 'Hi from frontend!' }),
            headers: {
              'Accept': 'application/json',
              'Content-Type': 'application/json'
            }
          }
        );

        if (res.ok) {
          const data = await res.json();
          console.log(data);
        }
      } catch (error) {
        console.error(error);
      }
    }

    postBackend();

  }, []);

Now the backend code:

app.get('/backend-to-frontend', (req, res) => {
    res.json({ message: 'Hi from backend!' });
});

app.post('/frontend-to-backend', (req, res) => {
    try {
        const reactMessage = JSON.parse(req.body.data);
        console.log(`message: ${reactMessage}`);
    } catch (err) {
        console.error(err);
    }
});

How to fix this? Please help!

Full backend server code can be found here:

const express = require("express");

const app = express();

app.use(express.urlencoded({ extended: true }));

app.get('/backend-to-frontend', (req, res) => {
    res.json({ message: 'Hi from backend!' });
});

app.post('/frontend-to-backend', (req, res) => {
    try {
        const reactMessage = JSON.parse(req.body.data);
        console.log(`message: ${reactMessage}`);
    } catch (err) {
        console.error(err);
    }
});

const port = process.env.PORT || 8000;

app.listen(port, function () {
    console.log(`Backend server started on port ${port}.`);
});

Upvotes: 1

Views: 2658

Answers (3)

Codecygen
Codecygen

Reputation: 121

I finally found the answer, here is my sample code. I did not change the React code that much so it is pretty much same, I removed the no cors section and added cors to Express JS code.

Here is my React code.

  // React-To-Node-Connection
  // "package.json" file has the following line
  // "proxy": "http://localhost:8000"
  // React Code
  useEffect(() => {
    const getBackend = async () => {
      const res = await fetch('/backend-to-frontend');
      const data = await res.json();

      if (!res.ok) {
        throw new Error(`Cannot get data from backend server. HTTP Status: ${res.status}`);
      }

      console.log(data.message);
    }

    getBackend();

    const postBackend = async () => {

      try {

        await fetch('http://localhost:8000/frontend-to-backend',
          {
            method: 'POST',
            body: JSON.stringify({ message: 'Hi from frontend!' }),
            headers: {
              'Content-Type': 'application/json'
            }
          }
        );

      } catch (err) {
        console.error(err);
      }
    }

    postBackend();

  }, []);

And here is my Express JS code.

const express = require("express");

const app = express();

app.use(express.urlencoded({ extended: true }));

// Express JS Code
const cors = require('cors');
app.use(express.json());
app.use(cors());

app.get('/backend-to-frontend', (req, res) => {
    res.json({ message: 'Hi from backend!' });
});

app.post('/frontend-to-backend', (req, res) => {
    try {
        console.log(req.body.message);
    } catch (err) {
        console.error(err);
    }
});

const port = process.env.PORT || 8000;

app.listen(port, function () {
    console.log(`Backend server started on port ${port}.`);
});

Thanks.

Upvotes: 0

traynor
traynor

Reputation: 8622

with no-cors, you can only use simple headers, so you cannot POST JSON (see: Supplying request options)

Try urlencoded:

   const postBackend = async() => {

     try {
       const res = await fetch('http://localhost:8000/frontend-to-backend', {
         method: 'POST',
         mode: 'no-cors',
         headers: {
           'Content-Type': 'application/x-www-form-urlencoded'
         },
         body: new URLSearchParams({
           'message': 'Hi from frontend!'
         })
       });

       if (res.ok) {
         const data = await res.json();
         console.log(data);
       }
     } catch (error) {
       console.error(error);
     }
   }

   postBackend();

and on the server, don't parse req.body, as it's already done by middleware:

app.post('/frontend-to-backend', (req, res) => {
    console.log('req.body: ', req.body);
    try {
        const reactMessage = req.body.message; 

Upvotes: 2

benek
benek

Reputation: 2178

req.body.data may be an object (check with debugger). If so, you might try to stringify before parsing :

JSON.parse(JSON.stringify(req.body.data))

Upvotes: 1

Related Questions