req.body empty on posts
Asked Answered
A

31

436

All of a sudden this has been happening to all my projects.

Whenever I make a post in nodejs using express and body-parser req.body is an empty object.

var express    = require('express')
var bodyParser = require('body-parser')

var app = express()

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded())

// parse application/json
app.use(bodyParser.json())

app.listen(2000);

app.post("/", function (req, res) {
  console.log(req.body) // populated!
  res.send(200, req.body);
});

Via ajax and postman it's always empty.

However via curl

$ curl -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:2000/

it works as intended.

I tried manually setting Content-type : application/json in the former but I then always get 400 bad request

This has been driving me crazy.

I thought it was that something updated in body-parser but I downgraded and it didn't help.

Any help appreciated, thanks.

Alcides answered 3/7, 2014 at 2:3 Comment(9)
So you tried explicitly setting the Content-Type in postman? If not, you might try that, as I've had issues before with postman not sending a Content-Type.Mclean
yes I did. that is when I recieved 400: invalid jsonAlcides
@Mclean - thanks i did not set content-tupe in postman and was getting crazy :)Cacodemon
For those people who are coming here because they wish to send/upload files from their APIs and thus have to use form-data. You need something to handle the form data: npmjs.com/package/multer is pretty popular package.Lagrange
No matter what, postman doesn't deal with integers and float values very well. If you have integer or float values, ensure to double quote everything, both keys and valuesGraft
Once change your content type to sth else and then again change it to json. this solved my problemKrissy
The real answer if you've done everything right - https://mcmap.net/q/80620/-req-body-empty-on-postsBeverie
what @Beverie linked to fixed it for me!Bohon
If anyone here is trying to set a content security policy (csp) reporting uri, the content type is often not application/javascript. See this answer for options: #64437436Frisk
E
408

In Postman of the 3 options available for content type select "X-www-form-urlencoded" and it should work.

Also to get rid of error message replace:

app.use(bodyParser.urlencoded())

With:

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

See https://github.com/expressjs/body-parser

The 'body-parser' middleware only handles JSON and urlencoded data, not multipart

As @SujeetAgrahari mentioned, body-parser is now inbuilt with express.js.

Use app.use(express.json()); to implement it in recent versions for JSON bodies. For URL encoded bodies (the kind produced by HTTP form POSTs) use app.use(express.urlencoded());

Estey answered 3/7, 2014 at 15:18 Comment(8)
That worked for postman, I'm not sure why it works with ajax as I didn't change anything.Alcides
For some reason http posts via Angular did not need to be URL encoded, but ajax calls did. Anyone know why?Flea
This worked for me, why wasn't it working with raw encoded though?Lucielucien
now body-parser is inbuilt with express.js just use app.use(express.json());Jeavons
I had the same problem. I made sure that I configured express correctly and the problem still occurred. The mistake was that I set the Content-Type in postman before making any requests and the problem was solved when I restarted postman.Lambent
for some reason, a request from another service to my app (a webhook) is parsed correctly when I use app.use(express.urlencoded());, but not with app.use(express.json()); (request.body is {}, an empty object). If anybody has an idea why, please share.Mazy
@SujeetAgrahari Make it an answer please. I also don't understand how express doesn't handle such basic by itself.Foreboding
It is worth noting that app.use(express.json()); needs to be placed before app.get/app.post to work.Madore
M
314

With Postman, to test HTTP post actions with a raw JSON data payload, select the raw option and set the following header parameters:

Content-Type: application/json

Also, be sure to wrap any strings used as keys/values in your JSON payload in double quotes.

The body-parser package will parse multi-line raw JSON payloads just fine.

{
    "foo": "bar"
}

Tested in Chrome v37 and v41 with the Postman v0.8.4.13 extension (body-parser v1.12.2 and express v4.12.3) with the setup below:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// ... Your routes and methods here

Postman raw json payload

Melesa answered 18/9, 2014 at 4:13 Comment(2)
Wrapping any strings used as key/values in double quotes... Easy to miss but a total deal breaker otherwise! Thank you.Trask
When use form-data in Postman to post the data, I always get the {} in the req.body. Should I set the Content-Type option?Silvanasilvano
S
102

I discovered, that it works when sending with content type

"application/json"

in combination with server-side
app.use(express.json())
(As @marcelocra pointed out, the 2022 version would use)

(old version for reference)
app.use(bodyParser.json());

Now I can send via

var data = {name:"John"}
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false); // false for synchronous request
xmlHttp.setRequestHeader("Content-type", "application/json");
xmlHttp.send(data);

and the result is available in request.body.name on the server.

Sylvester answered 6/6, 2017 at 0:36 Comment(9)
Thanks for the upvote. I really think this is the cleanest, although not the simplest solution, as you should send the correct content type anyways. I think.Sylvester
In my case I had to change it to xmlHttp.send(JSON.stringify(data));Cornela
What is bodyParser, where does it come from ?Foreboding
@AmbroiseRabier it is imported right after express.js in the original question. So an external library, basically.Sylvester
Per the other answers, seems like the most up-to-date way is using express.json() instead of bodyParser.json().Tole
Thanks mate, just did the edit. If you find more ways to improve the question or anser, please share!Sylvester
Make sure app.use(express.json()) is executed before your HTTP method declarations/mappingsBandler
You are my savior! Thank you!Schach
@Schach You are very welcome. I call it the SO-feeling :-) Enjoy your cool job! ;-)Sylvester
A
81

I made a really dumb mistake and forgot to define name attributes for inputs in my html file.

So instead of

<input type="password" class="form-control" id="password">

I have this.

<input type="password" class="form-control" id="password" name="password">

Now request.body is populated like this: { password: 'hhiiii' }

Agnesagnese answered 27/1, 2015 at 19:22 Comment(1)
This was my issue, thanks for pointing it outJenelljenelle
L
24

You have to check whether the body-parser middleware is set properly to the type of request(json, urlencoded).

If you have set,

app.use(bodyParser.json());

then in postman you have to send the data as raw.

https://i.stack.imgur.com/k9IdQ.png postman screenshot

If you have set,

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

then 'x-www-form-urlencoded' option should be selected.

Longish answered 9/6, 2018 at 11:25 Comment(1)
what about having both them? (bodyParser.urlencoded and bodyParser.json())... which one can I use in postman?Contaminant
C
22

I ran into this problem today, and what fixed it was to remove the content-type header in Postman! Very strange. Adding it here in case it helps someone.

I was following the BeerLocker tutorial here: http://scottksmith.com/blog/2014/05/29/beer-locker-building-a-restful-api-with-node-passport/

Candra answered 17/8, 2015 at 6:0 Comment(3)
i had the same issue. having the header "unchecked" (and greyed out) was not enough, i had to completely remove it. even though the "</>" source button shows that i was not sending that header with the Content-Type being in the unchecked state, it still needed to be completely removed.Prosenchyma
I can't figure out how to remove the default headers in the postman chrome extension... are you using the app maybe?Cavell
Oh, I installed the app and it works much better than the extension. Sorry for the noise.Cavell
C
22

If you are doing with the postman, Please confirm these stuff when you are requesting API

enter image description here

Conditioned answered 20/4, 2020 at 12:3 Comment(1)
this was the case for me. thank you.Humpage
G
20

For express 4.16+, no need to install body-parser, use the following:

const express = require('express');
const app = express();
app.use(express.json());

app.post('/your/path', (req, res) => {
    const body = req.body;
    ...
}
Gaines answered 23/11, 2020 at 15:3 Comment(1)
Solved it for me. Using it to get body of PUT request. body-parser returned empty json bodyRambort
S
18

Express 4.17.1

Server middleware example like this without bodyParser;

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

If you're GET requesting header should be like this;

{'Content-Type': 'application/json'}

If you're POST requesting header should be like this;

{'Content-Type': 'application/x-www-form-urlencoded'}

I'am using on client side simple functions like this;

async function _GET(api) {
    return await (await fetch(api, {
        method: 'GET',
        mode: 'no-cors',
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
            'Content-Type': 'application/json; charset=utf-8',
            'Connection': 'keep-alive',
            'Accept': '*',
        },
    })).json();
};

async function _POST (api, payload) {
    return await (await fetch(api, {
        method: 'POST',
        mode: 'no-cors',
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Connection': 'keep-alive',
            'Accept': '*/*',
        },
        body: new URLSearchParams(payload),
    })).json();
};
Sheenasheeny answered 9/10, 2021 at 12:4 Comment(2)
None of this is necessary. See this answer.Tole
This showed me I could use both app.use lines togetherAttendant
N
15

My problem was I was creating the route first

// ...
router.get('/post/data', myController.postHandler);
// ...

and registering the middleware after the route

app.use(bodyParser.json());
//etc

due to app structure & copy and pasting the project together from examples.

Once I fixed the order to register middleware before the route, it all worked.

Nassir answered 30/3, 2018 at 11:2 Comment(0)
B
10

In postman, even after following the accepted answer, I was getting an empty request body. The issue turned out to be not passing a header called

Content-Length : <calculated when request is sent>

This header was present by default (along with 5 others) which I have disabled. Enable this and you'll receive the request body.

Beverie answered 14/5, 2020 at 16:34 Comment(1)
Also, make sure the tool you are using for sending the requests sends the proper headers in general. In my case, I used a different tool with the exact same request and it worked.Sapro
G
9

The error source is not defining the specific header type when the postman request is made. I simply solved it by either adding

Content-Type: application/json

Or explicitly defining the raw data type as JSON in postman while making the request also solves the problem.

Grosvenor answered 31/5, 2021 at 3:55 Comment(2)
had to check Content-Lenght while making Postman request. Otherwise, it would throw an error.Inexertion
@ghimirehillson 's solution solved my problemCapp
M
4

Even when i was learning node.js for the first time where i started learning it over web-app, i was having all these things done in well manner in my form, still i was not able to receive values in post request. After long debugging, i came to know that in the form i have provided enctype="multipart/form-data" due to which i was not able to get values. I simply removed it and it worked for me.

Markmarkdown answered 26/10, 2016 at 9:48 Comment(2)
yes, this also worked to get the form body but then caused another problem with my form - basically the file could not be uploaded as this requires enctype="multipart/form-data"Cho
btw, just to add to my above comment, I managed to get this working with multer - see documentation on npmjs.com/package/multerCho
C
4

I solved this using multer as suggested above, but they missed giving a full working example, on how to do this. Basically this can happen when you have a form group with enctype="multipart/form-data". Here's the HTML for the form I had:

<form action="/stats" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <input type="file" class="form-control-file" name="uploaded_file">
    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
    <input type="submit" value="Get me the stats!" class="btn btn-default">            
  </div>
</form>

And here's how to use multer to get the values and names of this form with Express.js and node.js:

var multer  = require('multer')
var upload = multer({ dest: './public/data/uploads/' })
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
   // req.file is the name of your file in the form above, here 'uploaded_file'
   // req.body will hold the text fields, if there were any 
   console.log(req.file, req.body)
});
Cho answered 11/4, 2018 at 11:26 Comment(0)
D
3

Make sure ["key" : "type", "value" : "json"] & ["key":"Content-Type", "value":"application/x-www-form-urlencoded"] is in your postman request headers

Deafen answered 20/8, 2017 at 15:45 Comment(0)
N
3

It seems if you do not use any encType (default is application/x-www-form-urlencoded) then you do get text input fields but you wouldn't get file.

If you have a form where you want to post text input and file then use multipart/form-data encoding type and in addition to that use multer middleware. Multer will parse the request object and prepare req.file for you and all other inputs fields will be available through req.body.

Nippers answered 26/3, 2018 at 22:8 Comment(1)
thanks - multer was indeed the solution to my problem. It would be good if you could add an example on how to use this as part of your answerCho
N
3

I believe this can solve app.use(express.json());

Nunatak answered 11/8, 2019 at 3:55 Comment(0)
H
3

I solved this by changing the enctype of my form on the front-end:

  • It was ⛔️ <form enctype="multipart/form-data">
  • I changed it for ✅ <form enctype="application/json">

It was a relief to see the data eventually pop into the console ^^

Hardeman answered 24/3, 2021 at 9:45 Comment(1)
This was my problem, ever since I upgraded mongoose from v6 to v7 and using the latest nodejs.Spirochaetosis
T
2

A similar problem happened to me, I simply mixed the order of the callback params. Make sure your are setting up the callback functions in the correct order. At least for anyone having the same problem.

router.post('/', function(req, res){});
Thielen answered 25/1, 2017 at 16:33 Comment(1)
I solved my problems removing any express.json() express.urlencode() or bady-parse and writing so app.post('/path',function(req,res){ data="" // we can access HTTP headers req.on('data', chunk => { data+=chunk }) req.on('end', () => { console.log(data) js=JSON.parse(data) }) })Floorboard
P
2

I didn't have the name in my Input ... my request was empty... glad that is finished and I can keep coding. Thanks everyone!

Answer I used by Jason Kim:

So instead of

<input type="password" class="form-control" id="password">

I have this

<input type="password" class="form-control" id="password" name="password">
Papaya answered 16/7, 2019 at 11:57 Comment(0)
C
1

you should not do JSON.stringify(data) while sending through AJAX like below.

This is NOT correct code:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: JSON.stringify(data),
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}   

The correct code is:

function callAjax(url, data) {
    $.ajax({
        url: url,
        type: "POST",
        data: data,
        success: function(d) {
            alert("successs "+ JSON.stringify(d));
        }
    });
}
Choirmaster answered 12/4, 2018 at 6:22 Comment(1)
a key thing to note here is that in type, make sure you capitalize "POST". I've seen instances where just using "post" has lead to blank req.body.Disgrace
T
1

I had the same problem a few minutes ago, I tried everything possible in the above answers but any of them worked.

The only thing I did, was upgrade Node JS version, I didn't know that upgrading could affect in something, but it did.

I have installed Node JS version 10.15.0 (latest version), I returned to 8.11.3 and everything is now working. Maybe body-parser module should take a fix on this.

Theressa answered 16/1, 2019 at 18:58 Comment(0)
T
1

My problem was creating the route first require("./routes/routes")(app); I shifted it to the end of the code before app.listen and it worked!

Tithe answered 3/6, 2020 at 6:9 Comment(0)
O
1

Just a quick input - I had the same problem(Testing my private api with insomnia) and when I added the Content-Type: application/json, it instantly worked. What was confusing me was that I had done everything pretty much the same way for the GET and POST requests, but PUT did not seem to work. I really really hope this helps get someone out of the rabbit hole of debugging!

Occupation answered 22/7, 2021 at 14:18 Comment(0)
T
1

Make sure that you have removed the enctype attribute at the form tag when the form is not containing any file upload input

enctype='multipart/form-data
Tenderfoot answered 15/8, 2021 at 17:4 Comment(0)
L
1

Check your HTML tag name attribute

<input name="fname">

body-parser use tag name attribute to identify tag's.

Loverly answered 3/9, 2021 at 23:33 Comment(1)
Thanks, you have helped a backender from a two days html black holeFideicommissum
F
1

I simply solved the issue removing any .json() or .urlencode() for app.use() both for express and body-parser because they gave me some problems. I wrote my code recreating streaming with this simply solution

app.post('/mypath',function(req,res){
   data=""
   // we can access HTTP headers
   req.on('data', chunk => {
      data+=chunk
   })
   req.on('end', () => {
      console.log(data)
      // here do what you want with data
      // Eg: js=JSON.parse(data)
   })
}
Floorboard answered 19/10, 2021 at 23:34 Comment(0)
H
0

I was using restify instead of express and ran into the same problem. The solution was to do:

server.use(restify.bodyParser());
Handhold answered 20/1, 2017 at 1:12 Comment(0)
B
0

Change app.use(bodyParser.urlencoded()); in your code to

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

and in postman, in header change Content-Type value from application/x-www-form-urlencoded to application/json

Ta:-)

Birthmark answered 10/10, 2019 at 9:26 Comment(0)
R
0

Thank you all for your great answers! Spent quite some time searching for a solution, and on my side I was making an elementary mistake: I was calling bodyParser.json() from within the function :

app.use(['/password'], async (req, res, next) => {
  bodyParser.json()
  /.../
  next()
})

I just needed to do app.use(['/password'], bodyParser.json()) and it worked...

Rickrack answered 7/2, 2020 at 10:46 Comment(0)
D
0

In my case, I was using Fetch API to send the POST request and in the body, I was sending an object instead of a string.

Mistake -> { body: { email: 'value' } }

I corrected by stringifying the body -> { body: JSON.stringify({ email: 'value' }) }

Disobedience answered 26/5, 2021 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.