[node.js] Express.js req.body undefined

I have this as configuration of my Express server

app.use(app.router); 
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());

But still when I ask for req.body.something in my routes I get some error pointing out that body is undefined. Here is an example of a route that uses req.body :

app.post('/admin', function(req, res){
    console.log(req.body.name);
});

I read that this problem is caused by the lack of app.use(express.bodyParser()); but as you can see I call it before the routes.

Any clue?

This question is related to node.js express

The answer is


As already posted under one comment, I solved it using

app.use(require('connect').bodyParser());

instead of

app.use(express.bodyParser());

I still don't know why the simple express.bodyParser() is not working...


In case if you post SOAP message you need to use raw body parser:

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

app.use(bodyParser.raw({ type: 'text/xml' }));

var bodyParser = require('body-parser');
app.use(bodyParser.json());

This saved my day.


This occured to me today. None of above solutions work for me. But a little googling helped me to solve this issue. I'm coding for wechat 3rd party server.

Things get slightly more complicated when your node.js application requires reading streaming POST data, such as a request from a REST client. In this case, the request's property "readable" will be set to true and the POST data must be read in chunks in order to collect all content.

http://www.primaryobjects.com/CMS/Article144


To work, you need to app.use(app.router) after app.use(express.bodyParser()), like that:

app.use(express.bodyParser())
   .use(express.methodOverride())
   .use(app.router);

Building on @kevin-xue said, the content type needs to be declared. In my instance, this was only occurring with IE9 because the XDomainRequest doesn't set a content-type, so bodyparser and expressjs were ignoring the body of the request.

I got around this by setting the content-type explicitly before passing the request through to body parser, like so:

app.use(function(req, res, next) {
    // IE9 doesn't set headers for cross-domain ajax requests
    if(typeof(req.headers['content-type']) === 'undefined'){
        req.headers['content-type'] = "application/json; charset=UTF-8";
    }
    next();
})
.use(bodyParser.json());

In case anyone runs into the same issue I was having; I am using a url prefix like

http://example.com/api/

which was setup with router

app.use('/api', router); 

and then I had the following

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

What fixed my issue was placing the bodyparser configuration above app.use('/api', router);

Final

// setup bodyparser
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
    app.use('/api', router); 

app.use(express.json());

It will help to solve the issue of req.body undefine


The Content-Type in request header is really important, especially when you post the data from curl or any other tools.

Make sure you're using some thing like application/x-www-form-urlencoded, application/json or others, it depends on your post data. Leave this field empty will confuse Express.


This issue may be because you have not use body-parser (link)

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

var app = express();
app.use(bodyParser.json());

Latest versions of Express (4.x) has unbundled the middleware from the core framework. If you need body parser, you need to install it separately

npm install body-parser --save

and then do this in your code

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

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

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

I solved it with:

app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});

The middleware is always used as first.

//MIDDLEWARE
app.use(bodyParser.json());
app.use(cors());    
app.use(cookieParser());

before the routes.

//MY ROUTES
app.use("/api", authRoutes);

Wasted a lot of time:

Depending on Content-Type in your client request
the server should have different, one of the below app.use():

app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))

Source: https://www.npmjs.com/package/body-parser#bodyparsertextoptions

Example:

For me, On Client side, I had below header:

Content-Type: "text/xml"

So, on the server side, I used:

app.use(bodyParser.text({type: 'text/xml'}));

Then, req.body worked fine.


// Require body-parser (to receive post data from clients)

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

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

// parse application/json

app.use(bodyParser.json())

Most of the time req.body is undefined due to missing JSON parser

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

could be missing for the body-parser

const bodyParser  = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

and sometimes it's undefined due to cros origin so add them

const cors = require('cors');
app.use(cors())

This is also one possibility: Make Sure that you should write this code before the route in your app.js(or index.js) file.

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

If you are using some external tool to make the request, make sure to add the header:

Content-Type: application/json


Add in your app.js

before the call of the Router

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

No. You need to use app.use(express.bodyParser()) before app.use(app.router). In fact, app.use(app.router) should be the last thing you call.


First make sure , you have installed npm module named 'body-parser' by calling :

npm install body-parser --save

Then make sure you have included following lines before calling routes

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

app.use(bodyParser.json());

Use app.use(bodyparser.json()); before routing. // . app.use("/api", routes);


In my case, it was because of using body-parser after including the routes.

The correct code should be

app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(indexRoutes);
app.use(userRoutes);
app.use(adminRoutes);

Another possible way to get empty request.body when you forget the name attribute from the input element...

<input type="text" /> /* give back empty request.body -> {}*/
<input type="text" name="username" /> /* give back request.body -> {"username": "your-input"} */

Simple example to get through all:

Express Code For Method='post' after Login:

This would not require any such bodyParser().

enter image description here

app.js

const express = require('express');
const mongoose = require('mongoose');
const mongoDB = require('mongodb');

const app = express();

app.set('view engine', 'ejs');

app.get('/admin', (req,res) => {
 res.render('admin');
});

app.post('/admin', (req,res) => {
 console.log(JSON.stringify(req.body.name));
 res.send(JSON.stringify(req.body.name));
});

app.listen(3000, () => {
 console.log('listening on 3000');
});

admin.ejs

<!DOCTYPE Html>
<html>
 <head>
  <title>Admin Login</title>
 </head>
 <body>
   <div>
    <center padding="100px">
       <form method="post" action="/admin">
          <div> Secret Key:
            <input name='name'></input>
          </div><br></br><br></br>
          <div>
            <button type="submit" onClick='smsAPI()'>Get OTP</button>
          </div>
       </form>
    </center>
    </div >
</body>
</html>

You get input. The 'name' in "" is a variable that carries data through method='post'. For multiple data input, name='name[]'.

Hence,

on name='name' 

input: Adu
backend: "Adu"

OR

input: Adu, Luv,
backend: "Adu, Luv,"

on

name='name[]'
input: Adu,45689, ugghb, Luv
backend: ["Adu,45689, ugghb, Luv"]

express.bodyParser() needs to be told what type of content it is that it's parsing. Therefore, you need to make sure that when you're executing a POST request, that you're including the "Content-Type" header. Otherwise, bodyParser may not know what to do with the body of your POST request.

If you're using curl to execute a POST request containing some JSON object in the body, it would look something like this:

curl -X POST -H "Content-Type: application/json" -d @your_json_file http://localhost:xxxx/someRoute

If using another method, just be sure to set that header field using whatever convention is appropriate.


Mine was a text input and I'm adding this answer here regardless so it would help people. Make sure your encoding is set when parsing! I struggled to make it work until I set a proper value to it.

This was the error I was getting without using any parser:

error info: TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.

Received an instance of undefined at Function.from (buffer.js:327:9)

We do not have to use body-parser now in Express as others have already mentioned, but just that app.use(express.text()); did not solve my issue.

undefined now changed to Object. According to Express documentation, request body returns an empty object ({}) if Content-Type doesn't match (among others).

error info: TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.

Received an instance of Object at Function.from (buffer.js:327:9)

The encoding type you set needs to be on point as well. In my case, it was text/plain. You can change it to suit your needs like JSON, etc. I did this and voila! Worked like a charm!

app.use(express.text({
    type: "text/plain" 
}));

Credit to @spikeyang for the great answer (provided below). After reading the suggested article attached to the post, I decided to share my solution.

When to use?

The solution required you to use the express router in order to enjoy it.. so: If you have you tried to use the accepted answer with no luck, just use copy-and-paste this function:

function bodyParse(req, ready, fail) 
{
    var length = req.header('Content-Length');

    if (!req.readable) return fail('failed to read request');

    if (!length) return fail('request must include a valid `Content-Length` header');

    if (length > 1000) return fail('this request is too big'); // you can replace 1000 with any other value as desired

    var body = ''; // for large payloads - please use an array buffer (see note below)

    req.on('data', function (data) 
    {
        body += data; 
    });

    req.on('end', function () 
    {
        ready(body);
    });
}

and call it like:

bodyParse(req, function success(body)
{

}, function error(message)
{

});

NOTE: For large payloads - please use an array buffer (more @ MDN)


Looks like the body-parser is no longer shipped with express. We may have to install it separately.

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

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

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

// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!

Refer to the git page https://github.com/expressjs/body-parser for more info and examples.


You can try adding this line of code at the top, (after your require statements):

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

As for the reasons as to why it works, check out the docs: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions


Express 4, has build-in body parser. No need to install separate body-parser. So below will work:

export const app = express();
app.use(express.json());

adding express.urlencoded({ extended: true }) to the route solves the problem.

router.post('/save',express.urlencoded({ extended: true }),  "your route");

You can use express body parser.

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));

Okay This may sound Dumb but it worked for me.

as a total beginner, I didn't realized that writing:

router.post("/", (res, req) => {
  console.log(req.body);
  req.send("User Route");
});

is wrong !

You have make sure that you pass parameters(req,res) of post/get in right order: and call them accordingly:

router.post("/", (req, res) => {
  console.log(req.body);
  res.send("User Route");
});

UPDATE July 2020

express.bodyParser() is no longer bundled as part of express. You need to install it separately before loading:

npm i body-parser

// then in your app
var express = require('express')
var bodyParser = require('body-parser')
 
var app = express()
 
// create application/json parser
var jsonParser = bodyParser.json()
 
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
 
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
  res.send('welcome, ' + req.body.username)
})
 
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
  // create user in req.body
})

See here for further info

original follows

You must make sure that you define all configurations BEFORE defining routes. If you do so, you can continue to use express.bodyParser().

An example is as follows:

var express = require('express'),
    app     = express(),
    port    = parseInt(process.env.PORT, 10) || 8080;

app.configure(function(){
  app.use(express.bodyParser());
  app.use(app.router);
});

app.listen(port);
    
app.post("/someRoute", function(req, res) {
  console.log(req.body);
  res.send({ status: 'SUCCESS' });
});

in Express 4, it's really simple

const app = express()
const p = process.env.PORT || 8082

app.use(express.json()) 

For anyone who none of the answers above have worked for I had to enable cors between my front-end and express.

You can do this either by:

  1. Downloading and turning on a CORS extension for your browser, such as:

    https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

    for Chrome,

or by

  1. Adding the lines

    var cors=require('cors');
    
    app.use(cors());
    

to your express app.js page. (After npm install cors)


Latest version of Express already has body-parser built-in. So you can use:

const express = require('express);
... 
app.use(express.urlencoded({ extended: false }))
.use(express.json());

Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`

Examples related to express

UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block jwt check if token expired Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] npm notice created a lockfile as package-lock.json. You should commit this file Make Axios send cookies in its requests automatically What does body-parser do with express? SyntaxError: Unexpected token function - Async Await Nodejs Route.get() requires callback functions but got a "object Undefined" How to redirect to another page in node.js