Reputation: 4925
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.
Upvotes: 437
Views: 533482
Reputation: 350
For anyone experiencing this with multer it can also happen when you're passing more than two fields in formData, e.g. file and name.
// This will not work:
selectedFiles.forEach((file) => {
formData.append('file', file);
});
formData.append('uuid', uuid);
// But this will work
formData.append('uuid', uuid);
selectedFiles.forEach((file) => {
formData.append('file', file);
});
// File has to be the last one...
Upvotes: 0
Reputation: 2843
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.
Upvotes: 101
Reputation: 301
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)
})
}
Upvotes: 1
Reputation: 1092
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();
};
Upvotes: 17
Reputation: 9
Check your HTML tag name attribute
<input name="fname">
body-parser use tag name attribute to identify tag's.
Upvotes: 1
Reputation: 1191
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
Upvotes: 1
Reputation: 15
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!
Upvotes: 1
Reputation: 583
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.
Upvotes: 9
Reputation: 129
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' }) }
Upvotes: 0
Reputation: 61
I solved this by changing the enctype of my form on the front-end:
<form enctype="multipart/form-data">
<form enctype="application/json">
It was a relief to see the data eventually pop into the console ^^
Upvotes: 4
Reputation: 9464
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());
Upvotes: 413
Reputation: 7667
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;
...
}
Upvotes: 20
Reputation: 11
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!
Upvotes: 1
Reputation: 2214
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.
Upvotes: 11
Reputation: 2525
If you are doing with the postman, Please confirm these stuff when you are requesting API
Upvotes: 22
Reputation: 91
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...
Upvotes: 0
Reputation: 4011
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));
}
});
}
Upvotes: 1
Reputation: 1772
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:-)
Upvotes: 0
Reputation: 4436
I was using restify instead of express and ran into the same problem. The solution was to do:
server.use(restify.bodyParser());
Upvotes: 0
Reputation: 21
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">
Upvotes: 2
Reputation: 514
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.
Upvotes: 1
Reputation: 715
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.sstatic.net/k9IdQ.png postman screenshot
If you have set,
app.use(bodyParser.urlencoded({
extended: true
}));
then 'x-www-form-urlencoded' option should be selected.
Upvotes: 25
Reputation: 4717
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)
});
Upvotes: 4
Reputation: 15981
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.
Upvotes: 15
Reputation: 565
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
.
Upvotes: 3
Reputation: 71
Make sure ["key" : "type", "value" : "json"] & ["key":"Content-Type", "value":"application/x-www-form-urlencoded"] is in your postman request headers
Upvotes: 3
Reputation: 519
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){});
Upvotes: 2
Reputation: 1829
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.
Upvotes: 4
Reputation: 8662
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/
Upvotes: 22