50

I can't seem to recover the form-data of a post request sent to my Node.js server. I've put below the server code and the post request (sent using postman in chrome):

Post request

POST /api/login HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache

----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="userName"

jem
----WebKitFormBoundaryE19zNvXGzXaLvS5C

NodeJS server code

var express    = require('express');        // call express
var app        = express();                 // define our app using express
var bodyParser = require('body-parser');

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

app.all('/*', function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type,accept,access_token,X-Requested-With');
    next();
});

var port = process.env.PORT || 8080;        // set our port

var router = express.Router();              // get an instance of the express Router

router.get('/', function(req, res) {

    res.json({ message: 'I am groot!' });   
});

// Login
router.route('/login')

    .post(function(req, res){

        console.log('Auth request recieved');

        // Get the user name
        var user = req.body.userName;

        var aToken = getToken(user);

        res.json({

            'token':'a_token'
        });
    });

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

app.listen(port);

The login method tries to obtain the req.body.userName, however, req.body is always empty. I've seen other cases on SO describing such behavior but none of the related answers did apply here.

Thanks for helping out.

Zeeshan Hassan Memon
  • 8,105
  • 4
  • 43
  • 57
Jem
  • 6,226
  • 14
  • 56
  • 74
  • 3
    The issue is that the request's body is [a `multipart` message](http://en.wikipedia.org/wiki/MIME#Multipart_messages) and the `body-parser` module does not support parsing data in that format. The [2nd paragraph in its README](https://www.npmjs.org/package/body-parser#readme) offers suggestions for other modules you can use. – Jonathan Lonowski Oct 13 '14 at 19:51
  • 2
    Or, if the data in the `POST` request does not require `multipart`, it can be sent as [`x-www-form-urlencoded`](http://en.wikipedia.org/wiki/Percent-encoding#The_application.2Fx-www-form-urlencoded_type). This is the format that `bodyParser.urlencoded()` parses. – Jonathan Lonowski Oct 13 '14 at 20:17
  • Indeed, thanks for pointing out. My knowledge of HTTP is limited, so didn't knew about form-urlencoded. That way, my node.js can properly handle the post requests from the little angular frontend. Thanks for the help! – Jem Oct 13 '14 at 20:27

7 Answers7

45

In general, an express app needs to specify the appropriate body-parser middleware in order for req.body to contain the body.

[EDITED]

  1. If you required parsing of url-encoded (non-multipart) form data, as well as JSON, try adding:

    // Put this statement near the top of your module
    var bodyParser = require('body-parser');
    
    
    // Put these statements before you define any routes.
    app.use(bodyParser.urlencoded());
    app.use(bodyParser.json());
    

    First, you'll need to add body-parser to the dependencies property of your package.json, and then perform a npm update.

  2. To handle multi-part form data, the bodyParser.urlencoded() body parser will not work. See the suggested modules here for parsing multipart bodies.

cybersam
  • 63,203
  • 6
  • 53
  • 76
  • 3
    The OP shows `body-parser` is being used. The module does not, however, support `multipart` parsing. – Jonathan Lonowski Oct 13 '14 at 19:52
  • 1
    I've edited my answer to include a reference to suggested modules for multipart form parsing. Thanks to @Jonathan for the reference. – cybersam Oct 13 '14 at 20:24
  • Thanks for the help. Indeed, I was sending form-data, not knowing the server was able to accept url-encoded data. It works with the latter. – Jem Oct 13 '14 at 20:27
  • Will look at the pro&cons of url-encoded vs. form-data. Thanks again! – Jem Oct 13 '14 at 20:30
15

I followed this https://www.tutorialspoint.com/expressjs/expressjs_form_data.htm

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

// apply them

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

// how to use

router.post('/', function(req, res) {
    console.log(req.body);
    console.log('received the widget request');
});
7

To handle multipart/form-data request that support file upload, you need to use multer module. npm link for multer middleware

Sanjeev Kumar
  • 447
  • 1
  • 4
  • 10
5
  • For Json: Use body-parser.
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))

(you should Also send Content-Type: application/json in request header)

  • For Normal Form, Or multipart form (form with files), Use body-parser + multer.
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
app.use(multer().array())

(You should NOT send Content-Type: application/json in this case. you should send nothing, or Content-Type: multipart/form-data if you have files in form.

  • in postman you should not send Content-Type: multipart/form-data manually. otherwise you'll get an error (Boundary not found). (it will add this automatically.).)
yaya
  • 7,675
  • 1
  • 39
  • 38
3

Make sure to put in this order: bodyParser.json() first. app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true }));

Aecio Levy
  • 149
  • 1
  • 8
  • 1
    It'd be beneficial to have an explanation as to why. – Neithan Max Nov 12 '18 at 11:00
  • Carles Alcolea, Both are middleware that will be executed in this order. I have not looked the source code, But I would bet that with urlenconded first if the body is a JSON it might send an error back instead of skip and call the next middleware. This might be what the JSON module does, it is not a JSON, skip (call next()) instead of sending an error back and call the next middleware. – Aecio Levy Nov 13 '18 at 11:29
  • I meant it as in editing your answer adding a much-needed explanation for anyone who reads it. It's much more educative and clear when we justify our answers. It also helps us make sure we are sure of our answer ;P – Neithan Max Nov 30 '18 at 13:51
1

Make sure you are not sing enctype as multipart/form-data, body parser does not support it. use below line before you define any route.

app.use(bodyParser.urlencoded()); app.use(bodyParser.json());

Saifio
  • 321
  • 2
  • 4
0

I figured it out that in my case I was not using "name" attribute with the HTML input tags. I fixed it by changing:

This

<input id="first_name" />

To

<input id="first_name" name="first_name" />