sigil
sigil

Reputation: 9546

Trying to send form data to Express app, can't parse into req.body correctly

I know that a similar question has been asked many times, e.g. here.

However, I've tried applying various solutions from these answers without success.

Here's my client-side page:

<form id="submit_newuser" method="POST" action="/submit_newuser">
    User name:
    <input type="text" id="username" name="username" />
    <br>
    Phone number:
    <input type="text" id="phonenumber" name="phonenumber" />
    <br><br>
    <input type="submit" />
</form>

<script>
document.getElementById("submit_newuser").addEventListener('submit',submit_newuser);

function submit_newuser(event){
    event.preventDefault();
    submit_newuserForm=document.getElementById("submit_newuser");
    formData=new FormData(submit_newuserForm);
    fetch("/submit_newuser",{
        body:formData,
        headers:{
            "Content-Type": "application/json"
        },
        method:"post"
    })
    .then(response=>console.log(response))
    .catch(err=>"submit_newuser: error: "+err);
}
</script>

And here's the relevant server-side code for the /submit_newuser endpoint:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/submit_newuser',function(req,res){
    console.log("/submit_newuser: req.body: "+JSON.stringify(req.body));
    var phonenumber=req.body.phonenumber;
    var username=req.body.username;
    var output="you submitted: "+username+" "+phonenumber;
    console.log("/submit_newuser: text to send back: "+output);
    res.send(output);
});

With this, when I submit data from the page, the server logs this error:

SyntaxError: Unexpected token - in JSON at position 0

When I change the Content-Type to "application/x-www-form-urlencoded", I get this console logging:

/submit_newuser: req.body: {"------WebKitFormBoundaryBDU4OcntAv7d5wWL\r\nContent-Disposition: form-data; name":"\"username\"\r\n\r\ntestUserName\r\n------WebKitFormBoundaryBDU4OcntAv7d5wWL\r\nContent-Disposition: form-data; name=\"phonenumber\"\r\n\r\ntestPhoneNumber\r\n------WebKitFormBoundaryBDU4OcntAv7d5wWL--\r\n"}

/submit_newuser: text to send back: you submitted: undefined undefined

Which indicates that the data is being posted to the server, but not properly parsed into req.body.

Solutions involving multer don't seem to apply here because I'm not uploading a file, but I'm not sure if I should nonetheless be using a different approach than posting a FormData object in the fetch() body.

I'm confused, and also wondering if there's a simpler way to do this. I just want to post form data to the server without triggering a page refresh, and be able to update page elements with the server response.

Upvotes: 1

Views: 1676

Answers (3)

Mostafa Fakhraei
Mostafa Fakhraei

Reputation: 3687

If you're trying to send client's request as formData then you must handle your backend-side to receive request as formData.

There is a npm module called multer for handling formData request type.

Anyway your code must change to something like this:

Client-side

<script>

 document.getElementById("submit_newuser").addEventListener('submit',submit_newuser);

  function submit_newuser(event){
    event.preventDefault();
    submit_newuserForm=document.getElementById("submit_newuser");
    formData=new FormData(submit_newuserForm);
    fetch("http://127.0.0.1:3000/submit_newuser",{
        body:formData,
        method:"post"
    })
    .then(response=>console.log(response))
    .catch(err=>"submit_newuser: error: "+err);
}
</script>

Server-side

const multer = require('multer');
const upload = multer();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/submit_newuser', upload.none(), function (req, res) {
  console.log("/submit_newuser: req.body: " + JSON.stringify(req.body));
  var phonenumber = req.body.phonenumber;
  var username = req.body.username;
  var output = "you submitted: " + username + " " + phonenumber;
  console.log("/submit_newuser: text to send back: " + output);
  res.send(output);
});

Upvotes: 1

Terry Lennox
Terry Lennox

Reputation: 30685

You can update your client-side code to send a JSON body like so, this will be parsed correctly by the server.

Because we're setting the content-type header to JSON on the client, we must send JSON data. We could send url encoded data or multipart/form-data, however we would have to change headers on the client to do this.

document.getElementById("submit_newuser").addEventListener('submit',submit_newuser);

function formDataToJson(formData) {
    const obj = {};
    formData.forEach((value, key) => { 
        obj[key] = value
    });
    return JSON.stringify(obj);
}

function submit_newuser(event){
    event.preventDefault();
    submit_newuserForm=document.getElementById("submit_newuser");
    formData = new FormData(submit_newuserForm);
    fetch("/submit_newuser",{
        body: formDataToJson(formData),
        headers: {
            "Content-Type": "application/json"
        },
        method:"post"
    })
    .then(response=>console.log(response))
    .catch(err=>"submit_newuser: error: "+err);
}

Upvotes: 1

Mir Nawaz
Mir Nawaz

Reputation: 354

Use below sample ajax call for sending data from frontend.

var settings = {
  "async": true,
  "crossDomain": true,
  "url": "http://localhost:3000/submit_newuser",
  "method": "POST",
  "data": {
    "username": "test user",
    "phonenumber": "03453512545"
  }
}

$.ajax(settings).done(function (response) {
  console.log(response);
});

sample postman request.

enter image description here

Upvotes: 0

Related Questions