0

Question/Problem

My req.body is undefined when I post form data... This is strange because I have multiple other pages with forms where I post data the same way but all of a sudden I am getting this issue and I do not know why. This does seem to be a common problem but I can't find a fix that works for me.

What I have tried so far...

Code

<form action="/changePassword" method="post" onsubmit="event.stopPropagation(); return passwordChange(this);" enctype="application/x-www-form-urlencoded" novalidate="">
    <input id="password1" placeholder="password" name="password1" maxlength="30" class="form-control input-sm chat-input" type="password">
    <input id="password2" placeholder="confirm password" name="password2" maxlength="30" class="form-control input-sm chat-input" type="password">
    <input id="changePassword" value="Change Password" type="submit">
</form>

app.post('/changePassword', users.changePassword);

module.exports.changePassword = function(req, res){
    console.log(req.is('json')); // false and req.body is undefined
    ...
    ...        
    res.redirect('/'); 
});

Let me know if additional code is needed.

EDIT: Not sure if this is worth mentioning but I had other problems which again I did not have with other pages. When I was trying to validate the passwords, return false; would not prevent the page from posting/executing. I had to include event.stopPropagation().

Additional Code:

./bin/www

!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('app:server');
var http = require('http');
var express= require('express');

/**
 * Get port from environment and store in Express.
 */

var port = parseInt(process.env.PORT, 10) || 3000;

app.set('port', port);

/**
 * Create HTTP server.
 */

// var server = http.createServer(app);

//var server = app;

/**
 * Listen on provided port, on all network interfaces.
 */

app.use((err, req, res, next) => {
  console.log(err.stack || err.message);
  if (res.headersSent)
    return next(err)
  res.status(500).send('Internal Server Error')
})

app.listen(port);
app.on('error', onError);
app.on('listening', onListening);

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error('Port ' + port + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error('Port ' + port + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  debug('Listening on port ' + server.address().port);
}

app.js

/*jslint node:true */
/*global $, jQuery, alert*/
"use strict";
var express = require('express');
var path = require('path');
var fs = require('fs');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var expressSession = require('express-session');
var mongoose = require('mongoose');
var mongoStore = require('connect-mongo/es5')({ session: expressSession });
var passport = require('passport');
var debug = require('debug')('app:server');
var uriUtil = require('mongodb-uri');
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;

var assert = require('assert');


mongoose.Promise = global.Promise;

var MONGOLAB_URI = ****;
var mongooseUri = uriUtil.formatMongoose(MONGOLAB_URI);
var mongoConnection = mongoose.connect(MONGOLAB_URI, function (err, db) {
    if (err) {
        console.log('Unable to connect to MongoDB: ', err);

    } else {
        console.log('Connection has been established...');        
    }
});

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

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


app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

console.log("__dirname: " + __dirname);

app.use(expressSession({
    secret: 'RCNEfyBUAcHnPeQxFWyBTr',
    cookie: { maxAge: 60*60*1000 },
    resave: true,
    saveUninitialized: true
}));


app.use(passport.initialize());
app.use(passport.session());

require('./routes/index')(app, conn);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;
exports.mongoConnection = mongoConnection;

index.js

module.exports = function (app, conn) {
    ... 

    app.post('/signup', users.signup);
    app.post('/login', users.login)
    app.post('/changePassword', users.changePassword);                         
    app.post('/password', users.password); // send new password
    app.post('/user/create_test', users.create_test);
    app.post('/user/calculatesubjects', users.calculate_subjects);
    app.post('/user/calculatetopics', users.calculate_topics);
    app.post('/test/:username/:testid/:noq/:quesnum', users.answer_selected);

    // Admin posts
    app.post('/admin/update_subjects_topics', admin.update_subjects_topics);
    app.post('/admin/add_question', admin.add_question);
}

passwordChange function

function passwordChange(form) 
{
    if(form.password1.value != "" && form.password1.value == form.password2.value) {
      if(form.password1.value.length < 6) {
        alert("Error: Password must contain at least six characters!");
        form.password1.focus();
        return false;
      }

      re = /[a-z]/;
      if(!re.test(form.password1.value)) {
        alert("Error: password must contain at least one lowercase letter (a-z)!");
        form.password2.focus();
        return false;
      }
    } else {
      alert("Error: Please check that you've entered and confirmed your password!");
      form.password2.focus();
      return false;
    }

    return true;
}
Community
  • 1
  • 1
badinvestor
  • 67
  • 1
  • 10
  • `req.body` being undefined is almost always caused by the request handler (for `POST /changePassword`) being declared _before_ the `body-parser` middleware is declared. – robertklep Jul 30 '17 at 15:11
  • Can you give your passwordChange function!? – Yash Ganatra Jul 30 '17 at 15:20
  • @robertklep I don't understand why after several other pages this problem has just come up. I am including portions of my app.js and index.js code. Please see my additions at the bottom. – badinvestor Jul 30 '17 at 15:50
  • @badinvestor where (and how) do you load and use `index.js` in `app.js`? – robertklep Jul 30 '17 at 15:52
  • Thanks for he quick responses. I included ./bin/www, the first portion of app.js. index is being called at the end... – badinvestor Jul 30 '17 at 16:09
  • @badinvestor looking at your application setup, it looks like you used `express-generator` to set up the Express app structure. And since I don't see a `listen` anywhere, I assume that's actually more code than what you're showing. You should run through both `./bin/www` and `app.js` and check at which point(s) `body-parser` gets used, and where your routes are loaded. The former should be run before the latter. – robertklep Jul 30 '17 at 16:20
  • @robertklep Sorry, I was just trying to keep the amount of code to a minimum. I included all of `./bin/www` and `app.js`. After searching my documents I only call `body-parser` once at the top of app.js `var bodyParser = require('body-parser');`. – badinvestor Jul 30 '17 at 16:30
  • @badinvestor I took your exact code, and it seems to work as expected. Do you really mean that `req.body` is _undefined_, or do you mean it's _empty_ (i.e. `{}`)? – robertklep Jul 30 '17 at 16:43
  • @robertklep Yes, I meant `{ }`... it was req.body.password1 that was undefined. – badinvestor Jul 30 '17 at 17:09
  • @badinvestor there's a big difference between it being `undefined` and it being empty. Empty means that the request hits the `body-parser` middleware, but it can't do anything with the request. Undefined means it never hits the `body-parser` middleware, hence my questions about that. But that's apparently not the issue. – robertklep Jul 30 '17 at 17:11
  • Why is bodyParser.urlencoded used twice? – Froast Jul 30 '17 at 17:13

1 Answers1

0

It does sound like the problem is that the form is not being sent in JSON. By default html forms are sent as urlencoded (which you specified). Unless you are sending the form via javascript and specify json you should be using bodyParser.urlencoded:

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

I am confused to how other forms made similarly are working. The forms still can be sent via json if you use something like jQuery to send them via a script (and not with native html).

Froast
  • 742
  • 8
  • 16