Express and Mongoose: Cannot read property 'name' of undefined in Postman - javascript

I am attempting to create and insert 'user' json documents, defined in the model below, upon a POST request to localhost:3000/api/student. I am greeted with the following error using postman to send POST requests:
TypeError: Cannot read property 'name' of undefined
at module.exports.makeStudent (/home/tyler/Dropbox/Projects/Curricula/API/controllers/student.js:17:22)
at Layer.handle [as handle_request] (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/layer.js:95:5)
at next (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/layer.js:95:5)
at /home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/index.js:277:22
at Function.process_params (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/index.js:330:12)
at next (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/index.js:271:10)
at Function.handle (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/index.js:176:3)
at router (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/router/index.js:46:12)
Below are what I believe to be the relevant files
API/models/student.js
var mongoose = require('mongoose')
var studentSchema = new mongoose.Schema({
name: {type: String, required: true},
password: {type: String, required: true},
classes: [Number]
});
mongoose.model('Student', studentSchema);
API/controllers/student.js
var mongoose = require('mongoose');
var Student = mongoose.model('Student');
var sendJSONResponse = function(res, status, content){
res.status(status);
res.json({content});
}
module.exports.listStudents = function (req, res) {
sendJSONResponse(res, 200, {"status" : "success"});
};
module.exports.studentIDLookup = function (req, res) { };
module.exports.studentAuth = function (req, res) { };
module.exports.studentNametoID = function (req, res) { };
module.exports.makeStudent = function (req, res) {
Student.create({
name : req.body.name,
password : req.body.password,
email : req.body.email
}, function(err, student){
if(err){
sendJSONResponse(res, 400, err)
}
else{//success
sendJSONResponse(res, 201, student);
}
})
};
module.exports.deleteStudent = function (req, res) { };
app.js
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');
require('./API/models/db')
var app = express();
// view engine setup
app.set('views', path.join(__dirname,'app','views'));
app.set('view engine', 'jade');
//routes
var indexRoute = require('./app/routes/index');
app.use('/', indexRoute);
var apiRoute = require('./API/routes/index.js')
app.use('/api', apiRoute);
// 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: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// 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 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');
});
// Export app to module
module.exports = app;
Any insight to what I am doing wrong would be appreciated.

The order in which you declare routes/middleware is incorrect:
//routes
var indexRoute = require('./app/routes/index');
app.use('/', indexRoute);
var apiRoute = require('./API/routes/index.js')
app.use('/api', apiRoute);
// 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: false }));
This means that the body-parser middleware, which is used to populate req.body, won't get called for requests made to / and requests starting with /api, because those routes are declared before the body-parser middleware is declared.
The solution is to move body-parser (and logger as well, probably) to before the route declarations:
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//routes
var indexRoute = require('./app/routes/index');
app.use('/', indexRoute);
var apiRoute = require('./API/routes/index.js')
app.use('/api', apiRoute);

first of all, you should install body-parser using npm:
npm i --save body-parser
then, add it to your js file like below:
const bodyParser = require('body-parser');
for adding parser like urlencoded for post requests, use the below line:
const urlencodedParser = bodyParser.urlencoded({ extended: false });
finally, add urlencodedParser to your request as a middleware:
app.post('/', urlencodedParser, (req,res) => {})

Related

File Upload returning "undefined"

So I am using Express File Upload and when I attempt to send a post request to it, it returns the error from the error-handler that is set up, which essentially it couldn't find any files when I console.log(req.files) it returns undefined, which is why the error is being sent back, but I don't know how to fix the problem.
Index.js
router.post('/upload-avatar', async (req, res) => {
try {
console.log(req.files)
if(!req.files) {
res.send({
status: false,
message: 'No file uploaded'
});
} else {
//Use the name of the input field (i.e. "avatar") to retrieve the uploaded file
let avatar = req.files.avatar;
//Use the mv() method to place the file in upload directory (i.e. "uploads")
avatar.mv('./uploads/' + avatar.name);
//send response
res.send({
status: true,
message: 'File is uploaded',
data: {
name: avatar.name,
mimetype: avatar.mimetype,
size: avatar.size
}
});
}
} catch (err) {
res.status(500).send(err);
}
});
App.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const bodyParser = require('body-parser');
const _ = require('lodash');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
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(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
app.use(fileUpload({
createParentPath: true
}));
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// 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;
I am using an azure server, and at the moment I am using postman to get it working first!
Thanks In Advance!
Middlewares should be ordered appropriately. Your file upload middleware was placed below your index router. So when a request hits the server Express would run your indexRouter’s handler before the upload middleware and unless your handler calls next(), the file upload middleware would not process your request. And you cannot call next() since it would mean “I’m done with my part, hand this request (req) to the next middleware/handler”.
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const bodyParser = require('body-parser');
const _ = require('lodash');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
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(express.static(path.join(__dirname, 'public')));
app.use(fileUpload({
createParentPath: true
}));
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// 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;

req.body throws an empty {}

I am using body-parser but it's not working and I don't know what the problem is.
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const bodyParser = require('body-parser');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
//bodyParser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// 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;
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', redirection, function(req, res, next) {
res.redirect('index', {title: 'Home'});
});
router.get('/country', function(req, res, next) {
// CountryName
res.render('country',
{
title: 'Home',
mainJS: 'main.js',
//country: req.body.countries
});
console.log(req.body)
});
function redirection(req, res){
if (req.url == '/'){
res.redirect('/country');
}
}
module.exports = router;
In this code it throws {}
What is the problem?
Your server only receives a request body in POST (or PUT or PATCH) operations, not in GET operations. You don't have router.post() in your sample code, so it seems you are not handling POSTs. Therefore, no req.body.
You can find your https://example.com/?query=parameters&query2=parameters at req.params.query and req.params.query2.
You can't use the location bar of a browser to do a POST: they from a form posts or xhr / fetch operations.

404 error in Node.js when doing app.get with postgres as Db

I am learning Node.js through a tutorial to build a simple API.
I have my own postgres db and I am trying to retrieve a table and not use the sample db/dummy db in the tutorial. I am following everything in the tutorial, only thing is I am using my own db and getting 404 not found error.
My Index.js
var express = require('express');
var router = express.Router();
var db = require('../queries');
router.get('/api/preference', function(req,res){ res.send('hi'); })
module.exports = router;
Queries.js
var promise = require('bluebird');
var options ={
//Initialization options
promiseLib : promise
};
var pgp = require('pg-promise')(options);
var db = pgp({
host: 'localhost',
port: 5432,
database: 'pmc',
user: 'tarun',
password: 'pes'
});
var connectionstring = 'postgres://tarun:pes#localhost:5432/pmc';
var db = pgp(connectionstring);
//add query funtions
module.exports = {
getAllPreference : getAllPreference
};
function getAllPreference(req,res,next){
db.any('select * from core.preferences')
.then(function(data){
res.status(200)
.json({
status : 'success',
data : data,
message: 'Retrieved ALL preferences'
});
})
.catch(function (err) {
return next(err);
});
}
app.js
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 index = require('./routes/index');
var users = require('./routes/users');
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: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// 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 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;
Error
Error: Not Found
at D:\node-postgress-promises\app.js:32:13
at Layer.handle [as handle_request] (D:\node-postgress-promises\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (D:\node-postgress-promises\node_modules\express\lib\router\index.js:317:13)
at D:\node-postgress-promises\node_modules\express\lib\router\index.js:284:7
at Function.process_params (D:\node-postgress-promises\node_modules\express\lib\router\index.js:335:12)
at next (D:\node-postgress-promises\node_modules\express\lib\router\index.js:275:10)
at D:\node-postgress-promises\node_modules\express\lib\router\index.js:635:15
at next (D:\node-postgress-promises\node_modules\express\lib\router\index.js:260:14)
at Function.handle (D:\node-postgress-promises\node_modules\express\lib\router\index.js:174:3)
at router (D:\node-postgress-promises\node_modules\express\lib\router\index.js:47:12)
Blockquote
Change this portion of code as follow
exports.getAllPreference = function(req,res,next){
console.log('h');
db.any('select * from core.preferences')
.then(function(data){
res.status(200)
.json({
status : 'success',
data : data,
message: 'Retrieved ALL preferences'
});
})
.catch(function (err) {
next(err);
});
}
Remove below code in this file
module.exports = {
getAllPreference= getAllPreference
}
Change your index.js file Remove below lines
module.exports = {
getAllPreference: getAllPreference
};
function getAllPreference(req, res, next) {};
And uncomment
module.exports = router;
Add below code for testing purpose. in index.js file
router.get('/api/preference', function(req,res){
res.send('hi');
};

Unable to set separate route files in Express JS

I want to separate my login route from default app.js and route/index.js files but I'm not getting error 404 Not Found while executing localhost:3000/login
I know this questions has been asked already before and I've followed other answers on StackOverflow but not getting why I'm getting error.
Stack overflow question I followed:
How to separate routes on Node.js and Express 4?
I'm not getting why I'm getting this error.
app.js
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 expressValidator = require('express-validator');
var session = require('express-session');
var mongodb = require('./mongoDB');
var index = require('./routes/index');
var users = require('./routes/users');
var login = require('./routes/login'); //including login.js
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: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '/public')));
app.use(session({
name: 'mysession',
secret: 'some_secret',
saveUninitialized: false,
resave: true, cookie: {
secure: true
}}));
app.use('/', index);
app.use('/users', users);
app.use('/login', login);
mongodb.connectDatabase;
// 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 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;
route/login.js
var express = require('express');
var router = express.Router();
router.get('/login', function (req, res) {
res.send('exec');
});
module.exports = router;
localhost:3000/login
Not Found
404
Error: Not Found
at /home/jatin/Drive/OpenSource/sessionManager/app.js:44:13
at Layer.handle [as handle_request] (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:312:13)
at /home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:330:12)
at next (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:271:10)
at /home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:618:15
at next (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:256:14)
at Function.handle (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:176:3)
at router (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:46:12)
at Layer.handle [as handle_request] (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:312:13)
at /home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:330:12)
at next (/home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:271:10)
at /home/jatin/Drive/OpenSource/sessionManager/node_modules/express/lib/router/index.js:618:15
It's a little confusing, but when you use:
app.use('/login', login);
You are nesting all routes defined in login under the /login namespace. You can probably currently access the route at /login/login
Change your login.js to:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {
res.send('exec');
});
module.exports = router;
Then /login/ will correctly be routed to the / route of the login namespace

router.get function not being called

I am using passport.js for a basic log in/log out system. For some reason, the router.get('/signout', function(req, res)) is not being called when I run http://localhost:3000/auth/signout on Advanced rest client. Instead I am getting a Internal Server Error: 500. Login works just fine, but signout does not. Here is my app.js and authenticate.js:
App.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var passport = require('passport');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//Initialize models
require('./models/models.js');
var api = require('./routes/api');
var authenticate = require('./routes/authenticate')(passport);
var mongoose = require('mongoose');
//connect to mongodb
mongoose.connect("mongodb://localhost:27017/chirp-test");
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(session({
secret: 'super duper secret'
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session()); //This creates a unique has for our session
//Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);
app.use('/auth', authenticate);
app.use('/api', api);
// 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 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;
Authenticate.js
var express = require('express');
var router = express.Router();
module.exports = function(passport){
//sends successful login state back to angular
router.post('/success', function(req, res){
console.log('successful');
res.send({state: 'success', user: req.user ? req.user : null});
});
//sends failure login state back to angular
router.get('/failure', function(req, res){
res.send({state: 'failure', user: null, message: "Invalid username or password"});
});
//log in
router.post('/login', passport.authenticate('login', { failureRedirect: '/auth/failure' }),
function(req, res) {
//res.redirect('/auth/success');
res.send({state: 'success', user: req.user ? req.user : null});
});
//sign up
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
//log out
router.get('/signout', function(req, res) {
console.log('Signing out...');
req.logout();
res.redirect('/');
});
return router;
}
You have registered nothing under "/". So when "auth/logout" call redirect to redirect("/"), I guess client is redirected but goes into your "error handler" which sends a 500 error...

Categories