req.body undefined or empty - javascript

I have to two controllers and two separate routers.
bookController.js is work perfectly. Now I created userControllers to handle registration and login logic but req.body is empty. I tried to console.log to see if the form is being passed. but I get empty or undefined
I don't know what I am doing or what I have done wrong
Thanks
This is the app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
//const csurf = require('csurf');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var methodOverride = require('method-override')
//const multer = require('multer');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var bookRouter = require('./routes/book');
//Cross site request forgery
//const csrfMiddleware = csurf({cookie: true});
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
//app.use(csrfMiddleware);
app.use(methodOverride('_method'))
//app.use(multerConfig );
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/', bookRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
usersControllers.js
const knex = require('../model/connection');
exports.register = function(req, res)
{
//REGISTER USER FORM PAGE
res.render('user/register');
}
exports.registeruser = function(req, res, next)
{
//REGISTER USER HANDLE
console.log(req.body.username);
console.log(req.body.email);
console.log(req.body.password);
console.log(req.body.password1);
res.render('user/dashboard');
}
and this is routes/users.js
var express = require('express');
var router = express.Router();
var usersControllers = require('../controllers/usersControllers');
/* GET users listing. */
router.get('/dashboard', usersControllers.index);
router.get('/register', usersControllers.register);
router.get('/login', usersControllers.login);
router.post('/registeruser', usersControllers.registeruser);
module.exports = router;
This is the form
<%- include('../includes/layout'); %>
<div class="container">
<div class="row">
<div class="col-lg-3"></div>
<div class="col-lg-6">
<div class="card">
<div class="card-header bg-primary"> Create User </div>
<form id="c_form-h" class="" method="post" action="/users/registeruser" enctype="multipart/form-data" style="padding: 5px;">
<div class="form-group row">
<label for="username" class="col-6 col-form-label">Username</label>
<div class="col-12">
<input type="text" class="form-control" name="username" placeholder="Add UserName">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-6 col-form-label">Email</label>
<div class="col-12">
<input type="email" class="form-control" name="email" placeholder="Add Email">
</div>
</div>
<div class="form-group row">
<label for="password" class="col-6 col-form-label">Password</label>
<div class="col-12">
<input type="password" class="form-control" name="password" placeholder="Enter Password">
</div>
</div>
<div class="form-group row">
<label for="password1" class="col-6 col-form-label">Password</label>
<div class="col-12">
<input type="password" class="form-control" name="password1" placeholder="Enter Password Again">
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<div class="col-lg-3"></div>
</div>
</div>
<%- include('../includes/footer'); %>

Let’s try to keep this least technical.
Let’s say you are sending a html form data to node-js server i.e. you made a request to the server. The server file would receive your request under a request object. Now by logic, if you console log this request object in your server file you should see your form data some where in it, which could be extracted then, but whoa ! you actually don’t !
So, where is our data ? How will we extract it if its not only present in my request.
Simple explanation to this is http sends your form data in bits and pieces which are intended to get assembled as they reach their destination. So how would you extract your data.
Use something called “body-parser” which would do this for you.
body-parser parses your request and converts it into a format from which you can easily extract relevant information that you may need.
First of all require the following in your app.js file.
var bodyParser = require('body-parser')
and add the following line to make it work
app.use(bodyParser.urlencoded({extended: true}));

Short Answer: Although, you have data coming in URL, you've no way to use that data. Use bocy-parser package to fix this issue.
npm install body-parser --save
This installs the body-parser package. What this does is that it binds together the response data sent back so you can actually get to it and use it. Without it, you're just getting data to an endpoint without any way to use it.
Use the body parser like this:
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({extended: true}));
Then inside the function where you try to use the data back do something like
console.log(req.body.username);
console.log(req.body.email);
console.log(req.body.password);
console.log(req.body.password1);
I understand you already tried to implement the body-parser as you said above. Try making a separate endpoint for this. Instead of /users/registeruser, try doing this in a separate /registeruser endpoint and see if that works out. If it does, try again with some insight in endpoints setup, if not, comment further.

Related

Registration page should be route on /auth/register and display the message but it isn't getting redirected

I am creating a registration page but I'm having a problem after submitting. The page is not getting redirected and the page keeps loading until I refresh the page. I want it to be route on /auth/register and display the message
server.js page
var express = require("express");
var mysql = require("mysql");
var app = express();
var path = require("path");
var port = 8080;
app.use(express.urlencoded({extended:false}));
app.use(express.json());
app.set("view engine" , "hbs");
const routes = require("./routes/register.js");
app.use("/" ,routes);
app.use("/auth" , require("./routes/auth.js"));
app.listen(port);
index.hbs
<form action="/auth/register" method="POST">
Name : <input type="text" name="name">
Mobile :<input type="text" name="mobile">
Password :<input type="password" name="password">
<button class="saveBtn finModBtn" id="regConfirm">Confirm</button>
<button class="closeBtn finModBtn" id="regCancel">Cancel</button>
</form>
Routing pages
auth.js
After submitting, I want the message to be displayed on this page:
const express = require("express");
const router = express.Router();
var authController = require("../controller/auth.js");
router.post("/register" , function(req,res){
authController.register;
});
module.exports = router;
controller page
auth.js controller file
exports.register = function(req,res){
console.log(req.body);
res.send("form submitted");
}
I think there is some mistake in auth.js file of routing but am not able to figure it out.
You can try this change in /routes/auth.js
authController.register(req,res);

Use express js to pass form data to new page

I'm still fairly new to Express.js. I have a question about sending form data to an existing template. I have two routes which have template views associated with them. One page has a form on it and I want to take inputs from that form to populate the other template of the other route. I'm using Hanglebars for my template engine.
I've found a lot of helpful answers here (this one especially Cannot POST form node.js - express ), but none that quite answer my question.
I know how to post to create a new page with the form data. Like this:
router.post('/game', function(req, res) {
res.send(req.body.username);
});
But how do I get req.body.username accessible to a handlebars template? I've been reading various tutorials and it looks like I need to do something with next() in app.use('/game', game);. But I'm getting lost as to what exactly that is.
Here's a simplified version of my code.
My main server file:
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var http = require('http').Server(app);
var path = require('path');
var io = require('socket.io')(http);
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var routes = require('./routes/index');
var game = require('./routes/game');
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/game', game);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
http.listen(3000, function(){
console.log('listening on *:3000');
});
My route file "index.js":
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', {
title: 'Pick a Player',
});
});
module.exports = router;
Here is the form on index.handlebars (just the form):
<form method="post" action="/game" novalidate name="pick-a-player" id="pickAPlayer" class="form-box">
<p>What is your name?</p>
<input type="text" name="username" placeholder="name">
<p>Please select a player</p>
<label>
<input type="radio" name="player" value="Jane" checked> Jane<br>
<input type="radio" name="player" value="Sue"> Sue<br>
<input type="radio" name="player" value="Anne"> Anne<br>
</label>
<input type="submit" value="Start the game" id="submitCharacterForm">
</form>
I know I need to use post to get the data through req.body. But I'm getting the template through .get(). How do get the two to communicate?
Here's the route for game.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var router = express.Router();
/* GET Game page. */
router.get('/', function(req, res) {
res.render('game', {
title: 'Let's Play',
username: req.body.username,
player: req.body.player
});
});
module.exports = router;
When the value of player gets called on game.handlebars, it looks like this:
<p class="player-card">{{player}}</p>
If I'm understanding this correctly, the main form will have two values on the request body: username and player.
This form will make a POST request to /game according to your form block:
<form method="post" action="/game" ...>
You handle this POST request with the following route handler:
router.post('/game', function(req, res) {
res.send(req.body.username);
});
And you want to send the username and player values to your game template correct?
If I'm understanding this correctly, you can either res.redirect with data or simply render a different view with the data:
router.post('/game', (req, res) => {
const { username, player } = req.body
res.render('play-game', { username, player });
});

Restful API works locally but angular frontend won't work when deployed to heroku

So as mentioned in the title, I had this project working on my localhost but since I've deployed to heroku it doesnt. I can still access the DB via the api and display the json but the front end file doesn't work.
At the homepage I just get cannot GET /
Server.js
'use strict'
const express = require('express');
const app = express();
const bodyParser = require('body-parser'); // req.body
const cors = require('cors'); // 8080
const mongoose = require('mongoose');
const uriUtil= require('mongodb-uri');
let patients = require('./data');
const mongodbUri = 'mongodb://*********:***********#ds056009.mlab.com:56009/pt-db';
const mongooseUri = uriUtil.formatMongoose(mongodbUri);
const dbOptions = {};
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(cors());
//app.get('/', function(req, res) {
//res.sendFile(__direname + '/index.html')
//});
app.use('/api/patients', require('./api/patients/routes/post_patient'));
app.use('/api/patients', require('./api/patients/routes/get_patients'));
app.use('/api/patients', require('./api/patients/routes/get_patient'));
app.use('/api/patients', require('./api/patients/routes/put_patient'));
app.use('/api/patients', require('./api/patients/routes/delete_patient'));
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
mongoose.connect(mongooseUri, dbOptions, (err) => {
if (err) {
console.log(err);
}
console.log(`Our app is running on port ${ PORT }`);
});
});
public/js/app.js
(function() {
'use strict';
var app = angular.module('patientsApp', []);
app.controller('patientsController', function($scope, $http) {
$http.get('api/patients')
.then(function(response) {
$scope.patients = response.data;
});
$scope.savePatient = function(patient) {
$http.post('api/patients', patient)
.then(function(response) {
$scope.patients.push(response.data);
});
}
});
})();
public/index.html
<!DOCTYPE html>
<html ng-app="patientsApp">
<head>
<title>Patient DB</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body ng-controller="patientsController">
<div class="container">
<div class="col-sm-6">
<form ng-submit="savePatient(patient)">
<div class="form-group">
<input type="text" placeholder="First Name" ng-model="patient.first_name" class="form-control">
</div>
<div class="form-group">
<input type="text" placeholder="Last Name" ng-model="patient.last_name" class="form-control">
</div>
<div class="form-group">
<input type="text" placeholder="Hospital Number" ng-model="patient.hosp_num" class="form-control">
</div>
<div class="form-group">
<input type="text" placeholder="Consultant" ng-model="patient.consultant" class="form-control">
</div>
<div class="form-group">
<input type="text" placeholder="Treatment Site" ng-model="patient.treat_site" class="form-control">
</div>
<div class="form-group">
<input type="text" placeholder="Treatment Group" ng-model="patient.treat_group" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<div class="col-sm-6">
<ul class="list-group">
<li class="list-group-item" ng-repeat="patient in patients">
<h4>Patient Name: {{patient.first_name + ' ' + patient.last_name}}</h4>
<p>Hospital Number: {{patient.hosp_num}}</p>
<p>Consultant: {{patient.consultant}}</p>
<p>Treatment Site: {{patient.treat_site}}</p>
<p>Treatment Group: {{patient.treat_group}}</p>
</li>
</ul>
</div>
</div>
<script src="node_modules/angular/angular.js"></script>
<script src="/app.js"></script>
</body>
</html>
api/patients/gets_patients.js
const express = require('express');
const mongoose = require('mongoose');
const Patient = require('../model/Patient');
const router = express.Router();
router.route('/')
.get((req, res) => {
Patient.find({}, (err, patients) => {
if (err) {
res.status(400).json(err);
}
res.json(patients);
});
});
module.exports = router;
Hope this makes sense, any help would be greatly appreciated.
The main issue why you index.html was not loading was because you had commented out your middleware which serves your index.html.
Now that your index.html is served, It is not able to get the angular.js file which is because, the node_modules folder needs to be set to static for the node backend to serve the files.
You can do it like this :
var path = require('path');//Require the nodeJs's path module.
app.use('/', express.static(path.join(__dirname+'/node_modules')));//declare as static the node_modules folder so that node can serve the angular.js file inside it
EDIT :
app.use('/', express.static(path.join(__dirname+"/public")));
Also serve the /public folder which has the rest of your files the same way as above.
serve the angular.js file through cdn or create a bundle.js using webpack or gulp..serving node_modules will be a pain..

NodeJS express Post form - action always 404

No matter what link I declare in the action of my form, it always returns an 404 error. if I change the method to get, it doesn't.
I want to use post because i'm trying to get the data from my input fields and post it in my mongedb database:
HTML:
<form class="container-fluid searchContainer" action="/active" method="post">
<div class="col-xs-6">
<div class="form-group">
<label for="businessUnit">Business unit</label>
<input type="text" ng-model="businessUnit" id="businessUnit" name="businessUnit" class="form-control"/>
</div>
<div class="form-group">
<label for="tenderId">Tender ID</label>
<input type="text" name="tenderID" ng-model="tenderId" id="tenderId" class="form-control"/>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="tenderDate">Tender Bidding Date</label>
<input type="date" ng-model="tenderDate" name="tenderDate" id="tenderDate" class="form-control"/>
</div>
<div class="form-group">
<label for="therapyArea">Therapy area</label>
<input type="text" ng-model="therapyArea" name="therapyArea" id="therapyArea" class="form-control"/>
</div>
</div>
<div class="col-md-12 text-right">
<input type="submit" id="btnCreate" value="Create" class="btn btn-primary" >
</div>
</form>
JAVASCRIPT:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var active = require('./routes/active');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/active', active);
// 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;
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/tenders');
var db = mongoose.connection;
db.on('error', function(err) {
console.log('connection error', err);
});
db.once('open', function() {
console.log('connected.');
});
var Schema = new mongoose.Schema({
TenderID: String,
TenderDate: String,
BusinessUnit: String,
TherapyUnit: String
});
var Tender = mongoose.model('Tender', Schema);
app.post('/active', function(req, res) {
new Tender({
TenderID: req.body.tenderID,
TenderDate: req.body.tenderDate,
BusinessUnit: req.body.businessunit,
TherapyUnit: req.body.therapyUnit
}).save(function(err, doc) {
if (err) res.json(err);
else res.send('Succesfully insterted')
})
});
Because you define your 404 route handler before you define app.post('/active'), express evaluates the 404 rule first and returns it. Your POST /active route never gets evaluated. To fix this you need to give Express your POST /active route before your 404 route (which should always be your last route).
Unless you have an equivalent POST /active route defined in the file ./routes/active, the line
app.use('/active', active);
won't fix this problem even though it is evaluated before your 404 route. You can read more about app.use() vs app.get|post|etc() in the express docs.
Express evaluates rules in the order they are passed to it via use() or get|post|delete|etc()
You have defined get route in your server. Try to change the
app.get('/active',function(req,res){
into
app.post('/active',function(req,res){
In this way, you will respond to a post request from the browser.

CSURF not working

[Development Env] nodejs v4.2.4 + expressjs v4.13.1 + csurf v1.8.3
I successfully installed csurf middleware but It seems like not working.
I tried submitting form without csrf input field to test it works and there was nothing err. So I inserted console.log codes into router js file
console.log(res.locals._csrf);
and I recieved 'undefined'.
I inserted input field to verify the value exist, html result also had not csrfToken
<input name="_csrf" value="" type="hidden">
What can I do? This is html source
<form class="form" method="post" action="/login" role="form">
<input type="hidden" name="_csrf" value="{{_csrf}}">
<div class="form-group label-floating">
<label class="control-label" for="focusedInput1">User Name</label>
<input class="form-control" name="userName" id="focusedInput1" type="text">
</div>
<div class="form-group">
<div class="form-group label-floating">
<label class="control-label" for="focusedInput2">password</label>
<input class="form-control" name="user_pw" id="focusedInput2" type="password">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" style="float:left">Login</button>
<button type="button" class="btn btn-default" style="float:right" data-dismiss="modal">Cancel</button>
</div>
</form>
and This is app.js
// module importing
var express = require('express'),
path = require('path'),
favicon = require('serve-favicon'),
logger = require('morgan'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
exphbs = require('express-handlebars'),
mongoose = require('mongoose'),
csrf = require('csurf');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
var routes = require('./routes/index');
var users = require('./routes/users');
var credentials = require('./credentials.js');
var app = express();
// mongoose Setup
mongoose.connect(credentials.mongooseRsrc.collUrl);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('.hbs', exphbs({defaultLayout: 'single', extname: '.hbs'}));
app.set('view engine', '.hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(credentials.cookieSecret));
app.use(session({
resave: false,
saveUninitialized: false,
secret: 'sfbsesc',
store: new MongoStore({
mongooseConnection: mongoose.connection
})
}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use(csrf());
app.use(function(req, res, next){
res.locals._csrf = req.csrfToken();
});
//skip
I had the same issue and worked around it by passing the token in through the controller.
In your routes controller, for your POST /login, pass in the token as an object on response.
router.post('/login', (req, res) => {
res.render('login', {
_csrfToken: req.csrfToken(),
});
});
This could cause issues with other routes depending on how they're set up, but if you encounter errors saying token is invalid, you probably just need to pass it into that route as well

Categories