1

What i want to do is to read the property name of the request i send to my express.js server.Here is how i pass the json data to a post request.

document.querySelector('#checkout').onsubmit= async e =>{
    const form = new FormData(document.querySelector('#checkout'))
    let user = createUserInfo(form),
    

    order = {
       name: "Test_Name"
    }

    fetch("/checkout/create-order", {
        method: "POST",
        mode: "same-origin",
        redirect: 'manual',
        headers:{
            "Content-Type": "application/json"
        },
        body: JSON.stringify(
            {
                order: order,
                user: {
                   name:"test_Name"
                }

            }
        )
    }).then(res=>{
       res.ok
    }).then(data=>{
        console.log(data)
    })
}

And this is how i read it using express.js:

app.use(express.json());
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: false }));
const YOUR_DOMAIN = 'http://localhost:4242/checkout.html';

app.post('/checkout/create-order', async (req, res) => {
  console.log(req.body.order.name)
}

When i try to read the name property i get an error.

C:\xampp\htdocs\server.js:9
  console.log(req.body.order.name)
                             ^

TypeError: Cannot read properties of undefined (reading 'name')

2 Answers2

1

Add e.preventDefault() to the beginning of the onsubmit handler.

By default, when the user clicks a form submit button, the browser will send a URL encoded POST request to the URL defined in the form's action attribute (or if there is no action, the current page).

<form action="/somewhere_else"></form>

Your express code is seeing the request sent from the browser, which doesn't have any of the values you defined in the fetch request.

This also causes the page to reload and interrupt your fetch request code before its sent. By adding event.preventDefault() you suppress this behavior and your code should run as expected.

P.S. You don't need to use both express.json() and bodyparser.json(). Body-parser is included with Express, so both of those middlewares are doing the same thing. You can also use express.urlencoded() instead of bodyparser.urlencoded().

Elliot Hatch
  • 1,038
  • 1
  • 12
  • 26
  • Thank you for your reply, but this didn't work for me. I mean it works, but really weird. It outputs the 'name' property but afterwards says C:\xampp\htdocs\server.js:10 console.log(req.body.order.name) ^ TypeError: Cannot read properties of undefined (reading 'name') – Cristian Babalau Jul 02 '22 at 22:58
  • It sounds like either your browser is still sending two requests to the server (one that contains the correct body, and one with an empty body), or, you have server code somewhere (i.e. a middleware) that is modifying the request some reason before your POST handler processes it. Try opening the "Network" tab in your browser's dev tools before you click submit, and watch how many requests are logged. There should only be one. You should be able to view the request headers and body to see if the front-end is actually sending the data. Try changing server logging code to `console.log(req.body`)` – Elliot Hatch Jul 02 '22 at 23:24
  • Ok, so it logs out like this { order: { name: 'TREX' } }, everything seems ok to me – Cristian Babalau Jul 02 '22 at 23:44
  • Ok, i see what is going wrong here, it actually logs like { order: { name: 'TREX' } } {}, so there is one other object there and i have no clue where this one comes from – Cristian Babalau Jul 02 '22 at 23:44
  • So i fixed this error by deleting the action tag in the form, but now my stripe code for some reasons doesn't redirect me to the session – Cristian Babalau Jul 02 '22 at 23:47
  • In your fetch request you are passing the option `redirect: 'manual'`, which prevents the browser from following a 301 redirect response from the server. If you want to allow fetch to automatically redirect, you need to remove that option, or change the value to `follow` (the default). You will also need to tell your express handler to send a redirect response by calling `res.redirect(url)`. – Elliot Hatch Jul 03 '22 at 00:42
  • from origin 'http://localhost:4242' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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. – Cristian Babalau Jul 03 '22 at 00:46
  • i get the cors error although i use app.use(cors()) – Cristian Babalau Jul 03 '22 at 00:47
  • You can be getting the CORS error for a number of reasons, but since your POST request is coming from the same origin as the server (i.e. localhost), you shouldn't need to worry about CORS at all. A common mistake that will trigger the CORS error is mixing HTTP and HTTPS in your URLs (sending the request from https://localhost to http://localhost). Make sure they all match. – Elliot Hatch Jul 03 '22 at 00:58
  • The url i am trying to redirect to is a foreign link, it comes from stripe, so i guess it matters. – Cristian Babalau Jul 03 '22 at 01:02
  • Ah in that case, you're probably getting the error because the stripe endpoint doesn't support CORS, meaning you can't get data from it using fetch (or any Javascript) from your site. But it sounds like you don't want to redirect the fetch request, you want to redirect the browser to display the page? In that case, you need to get the redirect URL from the response and set the browser window location to that URL. See this answer https://stackoverflow.com/a/56974253 – Elliot Hatch Jul 03 '22 at 01:28
  • If you're not using fetch for a specific reason you could also avoid all these issues by using a normal URL-encoded form submit. You can still use Javascript to modify the inputs before they're sent in the request (https://stackoverflow.com/questions/6912197/change-value-of-input-and-submit-form-in-javascript), but you'll be letting the browser handle the actual sending of the POST request. If you do that, the browser should automatically follow the redirect without any other configuration. Your form tag would look something like this: `
    `
    – Elliot Hatch Jul 03 '22 at 01:29
  • Just a quick question, i get your idea, but could you provide me some futher help? Well i get the url link, it is not that big of a deal, but how should i pass it to the javascript so it will get redirected? Should i do a post request or what? – Cristian Babalau Jul 03 '22 at 04:11
  • I have another idea, what if i pass in the post request in express something like res.json({ok:"OK"}), will i be able to retrieve it in my fetch request like fetch(.....).then(res=>{console.log(JSON.stringify(res.json))}); – Cristian Babalau Jul 03 '22 at 04:31
1

Your server-side code is correct in my opinion, but a small tip, you don't need to use bodyparser.json() and express.json() both do the same thing. just chose one and stick to it.

Tyler2P
  • 2,324
  • 26
  • 22
  • 31