7

I've tried many StackOverflow answers, and this method normally works using body-parser, however I've been having issues with getting any output from req.body with either AJAX or form data.

In server.js:

app.use(helmet()); // Helmet middleware
app.use('/assets', express.static('resources/web/assets')); // Makes /assets public
app.use(require('./resources/modules/session.js')); // Custom session middleware
app.set('view engine', 'ejs'); // Sets EJS to the view engine
app.set('views', `${__dirname}/resources/web/pages`); // Sets the views folder
app.use(cookieParser()); // cookie-parser middleware
app.use(bodyParser.urlencoded({ extended: true })); // body-parser's middleware to handle encoded data
app.use(bodyParser.json()); // body-parser's middleware to handle JSON
app.use(fileUpload({ limits: { fileSize: 100 * 1024 * 1024 } })); // express-fileupload middleware (bushboy wrapper)
app.use('/api', require('./resources/routes/api.js')); // External API router
// ...
app.post('/login', (req, res) => {
    console.log(req.body);
    res.render('login', {
        config,
        page: {
            name: 'Login'
        },
        error: ''
    });
    res.end();
});

My login.ejs code:

            <form method="POST">
                <div class="input-group">
                    <i class="las la-user"></i>
                    <input placeholder="Username" name="username" type="text" required>
                </div>
                <div class="input-group">
                    <i class="las la-lock"></i>
                    <input placeholder="Password" name="password" type="password" required>
                </div>
                <button type="submit">
                    <i class="las la-paper-plane"></i> Login
                </button>
            </form>

No matter what I try, I always get an empty {} in the console with no avail. I've tried debugging; I need a fresh pair of eyes to see what I've done wrong. Here's the form data: Form Data And I've tried using jQuery's AJAX ($.get) too:

$.post('', {username:'test', password:'test'})
.fail(console.error)
.done(() => console.log('Success'));

enter image description here

Edit: After trying multer's app.use(require('multer')().array()); and app.use(require('multer')().none()); middleware, I'm still at the same old issue, except with multer req.body is now undefined instead of {}. This is due to the data being sent as application/x-www-form-urlencoded instead of what I previously thought was application/form-data. As that is the case, the body-parser middleware method should work. If contributing, please do not contribute an answer relating to parsing application/form-data!

Edit 2: For those asking for the session.js code, here it is:

const enmap = require('enmap'),
      sessions = new enmap('sessions');

module.exports = (req, res, next) => {
    if (!req.cookies) next();
    const { cookies: { session: sessionID } } = req;
    if (sessionID) {
        const session = sessions.get(sessionID);
        if (session) {
            req.session = session;
        } else {
            req.session = undefined;
        };
    } else {
        req.session = undefined;
    };
    next();
};

I'm attaching the whole source code as you people claim to be able to reproduce it somehow. Download it at https://dropfile.nl/get/F7KF (DM me on Discord if it isn't working - PiggyPlex#9993).

PiggyPlex
  • 631
  • 1
  • 4
  • 15
  • Normally, this should work. I am assuming you would have already done the next given steps but still would like to put those: 1. Is the request header (content type) properly being send - Check network tab? 2. Try using javascript fetch instead of jquery's post 3. and lastly, try hitting the request from API client like Postman to see if the behaviour is same. Might help you to narrow down the issue further. – Sunil Chaudhary Jul 01 '20 at 17:31
  • I've checked in network tab and tried with Insomnia. – PiggyPlex Jul 02 '20 at 09:25
  • 2
    I've run your code and it works for me. Would you please post code of `./resources/modules/session.js`? – macborowy Jul 03 '20 at 05:38
  • Even I have tried the same code pasted here and tested using postman, Ajax and jQuery as well. And it's working fine. – Nithish Jul 04 '20 at 10:51
  • Really? The only thing in there is some blank stuff. I'll attach them in the post. – PiggyPlex Jul 04 '20 at 22:19
  • 1
    The issue should be in one of the previous middlewares, try putting up your route, one line after another, you'll end up identifying the guilty one! – Johan Jul 07 '20 at 13:55

6 Answers6

16

For the specific case you're talking about, you usually need only 'body-parser' module to be able to access the form input fields. The minimum example that I advice you to build above it is the following:

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

var app = express();
app.use(bodyParser.urlencoded({extended : true}));
app.use(bodyParser.json());
app.get('/login', (req, res) => { /* ... */ });
app.post('/login', (req, res) => {
    console.log(req.body);
    // ...
});
  
app.listen(3000);

So my advice is to narrow on the cause of the problem by removing any other middleware except for the bodyParser. Try to comment them one-by-one and then you will be able to find the guilty!

Also note that no need to bother yourself trying to make it work with Ajax as it will make no difference. Keep it simple and just try the normal browser submission.

When you found the problematic middleware, debug it. If it's made by you, make sure that you don't make any changes to the req.body. If it a thirdparty middleware, so please consult their installation steps very carefully and I'm happy for further explanation and support

Edit: Some other hints

  • Make sure that the request is being submitted with the header Content-Type: application/x-www-form-urlencoded
  • Check if there any CORS problems
  • File upload middleware to be on a separate path just like the assets
Mouneer
  • 12,827
  • 2
  • 35
  • 45
  • Thanks - I found out that it was some dodgy session code as many of you pointed out! – PiggyPlex Jul 09 '20 at 10:40
  • @PiggyPlex Glad to hear that! Please mark this answer as the solution if you found it useful. – Mouneer Jul 09 '20 at 13:22
  • 1
    when to use `application/x-www-form-urlencoded` vs `application/json` as shown here: [https://stackoverflow.com/a/29823632](https://stackoverflow.com/a/29823632) ? – user1063287 Nov 21 '21 at 08:06
1

Removing enctype="multipart/form-data" from the form elements works for me, also after registering these middlewares:

app.use(express.json());
app.use(express.urlencoded({ extended: true })); 
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
PeterNg
  • 11
  • 2
1

Sometimes the main point this doesn't work is - when your data passed in the body is in text format, or as in my case in the headers I had 'Content-Type': 'application/x-www-form-urlencoded', but your req.body is expecting JSON data - so please make sure to double-check the 'Content-Type':'application/json' is set on the request headers.

Igor Kurkov
  • 4,318
  • 2
  • 30
  • 31
0

You need to use other module to deal with multipart/form-data https://github.com/pillarjs/multiparty

app.post('/login', function (req, res) {
  const form = new multiparty.Form();
  form.parse(req, function(err, fields, files) {
    console.log(fields);
  });
})
PiggyPlex
  • 631
  • 1
  • 4
  • 15
Eason
  • 469
  • 4
  • 14
-1

Please use body parser to get the input from the form

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

app.post('/anyRoute', (req, res) => {
    console.log(req.body); //your input value
});
  
app.listen(3000);
Ashish Choubey
  • 407
  • 1
  • 5
  • 17
-1

I had this same error and what fixed it was by removing enctype="multipart/form-data" from the form element. If you are not sending a file alongside the form with the enctype attribute, then you get such errors