bodyparser issue NodeJS express POST >" email undefined" - node.js

I am trying to store some user information in a MongoDB database.
From the front-end (AngularJS) on localhost:9000 I make a POST to the backend (express on localhost:3000)
I'm getting in the header information all the data, including the email-address.
but in the body email is undefined??
Console from Node server:
Console from Web browser:
I must do something wrong with the body parser?
Front-end:
registration View:
<form ng-submit="submit()" name="register" class="form-signin" novalidate>
<h1 class="form-signin-heading text-muted">Register</h1>
<input name="email" ng-model="email" type="email" class="form-control" placeholder="Email address" required autofocus="" required>
<p class="help-block" ng-show="register.email.$dirty && register.email.$invalid">Please enter a proper email.</p>
<input name="password" ng-model="password" type="password" class="form-control" placeholder="Password" required>
<input name="password_confirm" ng-model="password_confirm" type="password" class="form-control" placeholder="Confirm Password" validate-equals='password' required>
<p class="help-block" ng-show="register.password_confirm.$dirty && register.password_confirm.$invalid">please match the password.</p>
<button ng-disabled="register.$invalid" class="btn btn-lg btn-primary btn-block" type="submit">
Submit
</button>
</form>
Front-end controller:
'use strict';
angular.module('app')
.controller('RegisterCtrl', function ($scope, $http, alert) {
$scope.submit = function() {
var url = 'http://localhost:3000/register';
var user = {
email: $scope.email,
password: $scope.password
};
$http.post(url, user)
.success(function(res){
alert('success', 'OK!', 'You are now registered');
})
.error(function(err) {
alert('warning', 'Opps!', 'Could not register');
});
}
});
Back-end NodeJS express server.
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var app = express();
app.use(bodyParser.json());
//Verbind front-end met backend
app.use(function(req, res, next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
})
//MongoDB userModel
var User = mongoose.model('User', {
email: String,
password: String
});
//Reactie op de FRONT END POST voor REGISTRATIE
app.post('/register', function(req, res){
//emailVerification.s end(req.user.email);
//createSendToken(req.user, res);
var user = req.body;
console.log('req.body**' + req.body);
console.log('req.headers**' +req.headers);
var newUser = new User({
email: user.name,
password: user.password
})
newUser.save(function(err) {
//als goed opgeslagen > send status 200 en json new user
res.status(200).json(newUser);
console.log(newUser);
});
});
//MONGODB CONNECTIE =====================================
mongoose.connect('mongodb://....');
//MONGODB CONNECTIE =====================================
var server = app.listen(3000, function(){
console.log('api listening on ', server.address().port);
})
Thanks for your help.

Try using Dot operator , Change your Template as below,(sample code)
<form class="list" name="loginForm" ng-submit="login(credentials)" novalidate>
<label class="item item-input item-floating-label" for="username">
<span class="input-label">UserName</span>
<input type="text" placeholder="Username" id="username" ng-model="credentials.username">
</label>
<label class="item item-input item-floating-label" for="password">
<span class="input-label">Password</span>
<input type="password" placeholder="password" id="password" ng-model="credentials.password">
</label>
<button class="button button-block button-dark activated" type="submit">Logga in</button>
</form>
And in your Controller,
you get username as
var user = $scope.username;
Please read upon this article about Understanding Scopes
https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat
Happy Coding

I made a typo in "Back-end NodeJS express server"
var newUser = new User({
email: **user.name,**
password: user.password
})
must be:
var newUser = new User({
email: **user.email,**
password: user.password
})

Related

Body parser returning undefined for req.body request (SIMPLE LOGIN for beginner)

So I installed body parser via
npm i install express body-parser
and I wrote a simple code designed to input a user into an array after they complete a registration form.
but when I console.log the user it returns undefined for both email and password
here is the server code
const express = require('express');
const path = require('path');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const PORT = 3000;
var Users = [{"email":"mike#gmail.com", "password":"456"}];
app.get('/', (req, res) => {
res.render('index.ejs')
})
app.get('/Register.ejs', (req, res) => {
res.render('Register.ejs')
})
app.post('/views/Register.ejs', (req, res) =>
{
const newUser = {
email: req.body.email,
password: req.body.password
};
Users.push(newUser);
res.json(req.body.email);
console.log(Users)
}
)
app.listen(PORT);
here is the html for the register page
<h1>Please Register</h1>
<body>
<form action="/views/Register.ejs" method="POST">
<div class="div">
<label for="email">Enter Email</label>
<input type="email" id="email"for="email" id="email" required>
</div>
<div class="div">
<label for="password">Enter new password</label>
<input type="password" for="password" id="password" required>
</div>
<button type="submit"> Register </button>
</form>
</body>
Only installing body-parser is not enough. You have to put them in the code as middleware.
Top of the code use:
var bodyParser = require('body-parser');
and then use the code in somewhere middle of the code:
app.use(bodyParser.json())

req.body always empty when sending form via frontend

I'm just learning node and JS and therefore I built a very simple express-application with mongodb. The application is supposed to render a handlebars-template with a form to add users to the database.
My Problem is: When I send my form via the browser, req.body is always empty. When I send it via postman it works and the user gets added to my database. Why is that and what is missing for body-parser to parse my html-form.
Here is what I have so far:
app.js
const express = require('express'),
app = express(),
createError = require('http-errors'),
path = require('path'),
logger = require('morgan'),
bodyParser = require('body-parser'),
exphbs = require('express-handlebars');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(logger('dev')); // Log requests to API using morgan
app.set('views', './views');
app.engine('hbs', exphbs({
defaultLayout: 'main',
extname: 'hbs'
}));
app.set('view engine', 'hbs');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', require('./routes/routes'));
// 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 = process.env.NODE_ENV === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
views/adminAdd.hbs
<div class="row">
<form class="col s12" id="reg-form" action="/admin/add" name="add-form" enctype="application/x-www-form-urlencoded" method="post">
<div class="row py-md-2">
<div class="input-field col col-sm-6">
<input id="firstname" type="text" class="validate" required>
<label for="firstname">First Name</label>
</div>
</div>
<div class="row py-md-2">
<div class="input-field col col-sm-6">
<input id="lastname" type="text" class="validate" required>
<label for="lastname">Last Name</label>
</div>
</div>
<div class="row py-md-2">
<div class="input-field col col-sm-6">
<input id="email" type="email" class="validate" required>
<label for="email">Email</label>
</div>
</div>
<div class="row py-md-2">
<div class="input-field col col-sm-6">
<input id="password" type="password" class="validate" minlength="6" required>
<label for="password">Password</label>
</div>
</div>
<div class="row py-md-2">
<div class="input-field col-sm-6">
<button class="btn btn-large btn-register btn-primary" type="submit" name="adduser">Add User</button>
</div>
</div>
</form>
</div>
controllers/adminController
var util = require("util"),
adminUser = require("../models/adminUserModel");
exports.admin = function(req, res) {
res.render('admin', {
showNavBar: true,
showFooter: false,
title: 'Admin'
});
};
exports.adminAddGET = function(req, res) {
res.render('adminAdd', {
showNavBar: true,
showFooter: false,
title: 'Admin Add'
});
};
exports.adminAddPOST = function(req, res) {
console.log("req.body=" + util.inspect(req.body));
if(!req.body.firstname) {
res.json({ success: false, message: 'Please provide firstname.' });
} else if (!req.body.lastname) {
res.json({ success: false, message: 'Please provide lastname.' });
} else if (!req.body.email) {
res.json({ success: false, message: 'Please provide email.' });
} else if (!req.body.password) {
res.json({ success: false, message: 'Please provide password.' });
} else {
console.log("All Fields filled");
var newAdminUser = new adminUser({
firstname: req.body.firstname,
lastname: req.body.lastname,
email: req.body.email,
password: req.body.password
});
console.log("newAdminUserObject=" + util.inspect(newAdminUser));
// Attempt to save the user
newAdminUser.save(function(err) {
if (err) {
console.log("error:" + err);
return res.json({ success: false, message: 'ERROR - Didnt work' });
}
console.log("success");
res.json({ success: true, message: 'User added successfully!' });
});
}
};
routes/routes.js
var express = require('express'),
router = express.Router(),
adminController = require('../controllers/adminController'),
indexController = require('../controllers/indexController');
router.get('/', indexController.index);
router.get('/admin', adminController.admin);
router.get('/admin/add', adminController.adminAddGET);
router.post('/admin/add', adminController.adminAddPOST);
module.exports = router;
When sending the following form via postman...
Postman x-www-form-urlencoded
I see the following output in my terminal and the user is added successfully to my mongodb:
req.body={ firstname: 'dan',
lastname: 'dan',
email: 'dan#dan.de',
password: 'dandan' }
All Fields filled
newAdminUserObject={ role: 'Admin',
_id: 5b106939991dda2404c0dc6a,
firstname: 'dan',
lastname: 'dan',
email: 'dan#dan.de',
password: 'dandan' }
success
When I send the form via the browser, I get the following output:
req.body={ adduser: '' }
and in the browser I see the following:
browser output
From my perspective I'm sending the form with x-www-form-urlencoded in both ways to the same address.
Your form input elements are missing 'name' attributes. The reason you are getting { adduser: '' } is because the only input element in the form that has a name attribute is the button element.
<input id="firstname" name="firstname" type="text" class="validate" required>
<input id="email" name="email" type="email" class="validate" required>
...etc

Why am I getting a HTTP 400 error?

I found that the 400 HTTP error is something with syntax but I cannot find anything wrong with my syntax, could someone help take a look at it?
<!- My form view-->
<h3>Login</h3>
<form action="/home/login" method="post">
Enter your usernmae: <input type="text" name="user" value=""><br>
Enter your password: <input type="password" name="pwd" value=""><br>
<input type="submit" name="enter" value="Enter">
</form>
//controller added to my app.js
app.use('/home', indexController);
//in router.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
router.post('/login', passport.authenticate('local'), function(req, res) {
req.session.save(function (err) {
if (err) {
return next(err);
}
res.redirect('/home/' + req.user.user);
});
});

Express4 and Formidable file upload works until I enable csrf

I am working through Ethan Brown's book "Web Development with Node and Express" and it has been going well until I got to enabling csrf the multipart/form-data upload on the photo upload. I downloaded the full book code from Github, https://github.com/EthanRBrown/web-development-with-node-and-express and that does the same thing, works until csrf is enabled then it errors with:
Error: invalid csrf token
here are the bits of code I think are relevant, /meadowlark.js starting at line 100
app.use(require('cookie-parser')(credentials.cookieSecret));
app.use(require('express-session')({ store: sessionStore,
secret: credentials.cookieSecret,
name: credentials.cookieName,
saveUninitialized: true,
resave: true }));
app.use(express.static(__dirname + '/public'));
app.use(require('body-parser')());
// cross-site request forgery protection
app.use(require('csurf')());
app.use(function(req, res, next){
res.locals._csrfToken = req.csrfToken();
next();
});
// database configuration
var mongoose = require('mongoose');
var options = {
server: {
socketOptions: { keepAlive: 1 }
}
};
Then in /handlers/contest.js
var path = require('path'),
fs = require('fs'),
formidable = require('formidable');
// make sure data directory exists
var dataDir = path.normalize(path.join(__dirname, '..', 'data'));
var vacationPhotoDir = path.join(dataDir, 'vacation-photo');
fs.existsSync(dataDir) || fs.mkdirSync(dataDir);
fs.existsSync(vacationPhotoDir) || fs.mkdirSync(vacationPhotoDir);
exports.vacationPhoto = function(req, res){
var now = new Date();
res.render('contest/vacation-photo', { year: now.getFullYear(), month: now.getMonth() });
};
function saveContestEntry(contestName, email, year, month, photoPath){
// TODO...this will come later
}
exports.vacationPhotoProcessPost = function(req, res){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files){
if(err) return res.redirect(303, '/error');
if(err) {
res.session.flash = {
type: 'danger',
intro: 'Oops!',
message: 'There was an error processing your submission. ' +
'Pelase try again.',
};
return res.redirect(303, '/contest/vacation-photo');
}
var photo = files.photo;
var dir = vacationPhotoDir + '/' + Date.now();
var path = dir + '/' + photo.name;
fs.mkdirSync(dir);
fs.renameSync(photo.path, dir + '/' + photo.name);
saveContestEntry('vacation-photo', fields.email,
req.params.year, req.params.month, path);
req.session.flash = {
type: 'success',
intro: 'Good luck!',
message: 'You have been entered into the contest.',
};
return res.redirect(303, '/contest/vacation-photo/entries');
});
};
exports.vacationPhotoEntries = function(req, res){
res.render('contest/vacation-photo/entries');
};
and the views/contest/vacation-photo.handlebars
<form class="form-horizontal" role="form"
enctype="multipart/form-data" method="POST"
action="/contest/vacation-photo/{{year}}/{{month}}">
<input type="hidden" name="_csrf" value="{{_csrfToken}}">
<div class="form-group">
<label for="fieldName" class="col-sm-2 control-label">Name</label>
<div class="col-sm-4">
<input type="text" class="form-control"
id="fieldName" name="name">
</div>
</div>
<div class="form-group">
<label for="fieldEmail" class="col-sm-2 control-label">Email</label>
<div class="col-sm-4">
<input type="email" class="form-control" required
id="fieldName" name="email">
</div>
</div>
<div class="form-group">
<label for="fieldPhoto" class="col-sm-2 control-label">Vacation photo</label>
<div class="col-sm-4">
<input type="file" class="form-control" required accept="image/*"
id="fieldPhoto" data-url="/upload" name="photo">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
What is the proper way to make csrf work?
Thanks,
On vacation-photo GET request, you should send csrf token like below.
exports.vacationPhotoEntries = function(req, res){
res.render('contest/vacation-photo/entries', { _csrfToken: req.csrfToken()});
};
You can also catch csrf token error in your default error handler like below.
// error handler
app.use(function (err, req, res, next) {
if (err.code !== 'EBADCSRFTOKEN') return next(err)
// handle CSRF token errors here
res.status(403)
res.send('session has expired or form tampered with')
})
For more info, please check this link.
Append csrf token as query string to action Url..
It works!
<form class="form-horizontal" role="form" enctype="multipart/form-data" method="POST"
action="/contest/vacation-photo/{{year}}/{{month}}?_csrf={{_csrfToken}}">
</form>

Node.js + express : rewrite url path

I'd like to know if it's possible to rewrite an url with express.
I actually have this code :
var http, express, app;
http = require("http");
express = require("express");
app = express();
app.use(express.json())
app.use(express.urlencoded())
.post("/ajax_login", function (req, res) {
"use strict";
http.get({ host: "localhost", port: 8080, path: "/users/" + req.body.email + "/email" }, function (resp) {
resp.setEncoding("utf8");
resp.on("data", function (data) {
json = JSON.parse(data);
if (json.password.password === sha1(req.body.password)) {
res.render("home.ejs");
} else {
res.render("login.ejs", { email : req.body.email, error : "password is not good" });
}
});
});
})
.get("/login", function (req, res) {
"use strict";
res.render("login.ejs");
})
.listen(3030);
I call /ajax_login from a form :
<form method="post" action="/ajax_login">
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" name="email" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" />
</div>
<button type="submit" class="btn btn-primary">Connection</button>
</form>
The problem is : when I call /ajax_login, after res.render my HTML code on my browser is changed, but the url still /ajax_login.
How I can change this URL ?
I know the javascript solution :
window.history.pushState("", document.title, "/login");
But, I'd like to know if a solution exist from the server.
Thanks
I would add an error to the request locals, redirect to login, and then check if an error exists when rendering the login page.
.post("/ajax_login", function (req, res) {
"use strict";
...
if (password && email IS OK) {
res.locals.errorMSG = "password is not good";
res.redirect("/login"); //redirect vs render
} else {
res.render("home.ejs");
}
})
.get("/login", function (req, res) {
"use strict";
res.render("login.ejs", {error: res.locals.errorMSG || null});
})
res.locals
res.redirect

Resources