Regarding route defining in express framework of node js - javascript

I am setting up the route in my app.js file. And I am passing a route for the listing of flights in the routes/flights.js file. But the problem I am facing when I am defining the route at the bottom of all route I am getting 404 error but I pass same route definition at top of all route then it is working. Please help me with this code are given below of both files. Thanks in advance.
app.js file:
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var flightRouter = require('./routes/flight');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(function(req, res, next){
res.set('X-Powered-By', 'Flight Tracker');
next();
});
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/flight', flightRouter);
// 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;
routes/flight.js
var express = require('express');
var router = express.Router();
var flights = require('../modules/data');
var flight = require('../modules/flight');
for (var number in flights) {
flights[number] = flight(flights[number]);
}
router.get('/list', function (req, res, next) {
// console.log('in list');
res.render('flight', {
title: 'All flights',
flights: flights
});
});
router.get('/:id', function (req, res, next) {
var number = req.params.id;
if (typeof flights[number] === 'undefined') {
res.status(404).json({
status: 'error'
});
} else {
res.json(flights[number].getInformation());
}
});
router.put('/:id/arrived', function (req, res, next) {
var number = req.params.id;
if (typeof flights[number] === 'undefined') {
res.status(404).json({
status: 'error'
});
} else {
flights[number].triggerArrive();
res.json({
status: 'Done'
});
}
});
module.exports = router;
router.get('/list', function (req, res, next) {
res.render('flight', {
title: 'All flights',
flights: flights
});
});
this above line of code needs to work at bottom of other routes in routes/flight.js

If you mean inside the flights.js file....
This may be happening because the /:id also captures the /list route since :id doesn't have any constraints thats why it must be defined before /:id
Then the router will match /list and if there isn't a match, it will go to /:id

Related

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.

Router returns 404 in Express.js

I'm currently learning and a newbie to Node.js. I'm trying to build a simple REST API and currently getting an error 404 when try post to a particular route in postman to test if data has successfully been sent to Mongo db. I'm sure what i'm missing. I have double checked all my routes and they seem fine. It works when i make a get request and falls through when i make a post request.
This is my app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var Developer = require('./models/developers');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Connect to DB
mongoose.connect('mongodb://127.0.0.1:27017');
// API Routes
var router = express.Router();
// Routes will be prefixed with /api
app.use('/api', router);
// 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;
// Test Route
router.get('/', function (req, res) {
res.json({message: 'Welcome to my simple API!'});
});
router.route('/developers')
.post(function (req, res) {
var developer = new Developer(); // New instance of sa developer
developer.firstName = req.body.firstName;
developer.lastName = req.body.lastName;
developer.jobTitle = req.body.jobTitle;
developer.save(function (err) {
if (err) {
res.send(err);
} else {
res.json('Developer was successfully fetched');
}
});
})
.get(function (req, res) {
Developer.find(function (err, developers) {
if (err) {
res.send(err);
} else
res.json(developers);
});
});
router.route('/developer/:developer_id')
.get(function (req, res) {
Developer.findById(res.params.developer_id, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
router.route('/developer/firstName/:firstName')
.get(function (req, res) {
Developer.find({firstName:res.params.firstName}, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
My model is developer.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var DevelopersSchema = new Schema({
firstName: String,
lastName: String,
jobTitle: String
});
module.exports = mongoose.model('Developers', DevelopersSchema);
To connect the database, instead of
mongoose.connect('mongodb://127.0.0.1:27017');
Use,
mongoose.connect('mongodb://127.0.0.1:27017/yourDatabaseName');
Check the doc.
Mongoose database connection require a database name in connect() method.
Your final app.js should be like,
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var Developer = require('./models/developers');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Connect to DB
mongoose.connect('mongodb://127.0.0.1:27017/my_unique_data_base_name');
// API Routes
var router = express.Router();
// Routes will be prefixed with /api
app.use('/api', router);
// 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;
// Test Route
router.get('/', function (req, res) {
res.json({message: 'Welcome to my simple API!'});
});
router.route('/developers')
.post(function (req, res) {
var developer = new Developer(); // New instance of sa developer
developer.firstName = req.body.firstName;
developer.lastName = req.body.lastName;
developer.jobTitle = req.body.jobTitle;
developer.save(function (err) {
if (err) {
res.send(err);
} else {
res.json('Developer was successfully fetched');
}
});
})
.get(function (req, res) {
Developer.find(function (err, developers) {
if (err) {
res.send(err);
} else
res.json(developers);
});
});
router.route('/developer/:developer_id')
.get(function (req, res) {
Developer.findById(res.params.developer_id, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
router.route('/developer/firstName/:firstName')
.get(function (req, res) {
Developer.find({firstName:res.params.firstName}, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
if I'm correct, the line of app.use('/api', router); does nothing.
When coming a request for /api endpoint, a response should be sent at the end of operations. The code pass the request to router. And router does nothing.
Then if createError(404) method calls res.send() or res.end() methods
you should move the use() method to the bottom of your code page:
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
Because at every single time it works before the other routes.
IMHO, using a standard coding style make more readable the program-flow.
Good luck..

How to access app.locals variable in handlebars

app.js
var debug = require('debug');
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');
javvar mongoose = require('mongoose');
var session = require('express-session');
var db = require('./dbconn');
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('we are connected!');
});
var index = require('./routes/index');
var users =
require('./routes/users');
var signup = require('./routes/signup');
var login = require('./routes/login');
var adreqform =
require('./routes/adreqform') var dashboard =
require('./routes/dashboard')
var app = express();
// view engine setup app.set('views', path.join(__dirname, 'views'));
app.engine('hbs', exphbs({
extname: '.hbs',
defaultLayout: 'layout'
}));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(__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({
secret: 'gh jewellery',
resave: true,
saveUninitialized: false
}));
app.use(function(req, res, next) {
app.locals.currentUser = req.session.user;
next();
});
app.use('/', index);
app.use('/users', users);
app.use('/dashboard',
dashboard);
app.use('/signup', signup);
app.use('/login', login);
app.use('/adreqform', adreqform);
// 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: {}
});
});
app.set('port', process.env.PORT || 3000);
module.exports = app;
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
Notice I assign app.locals.currentUser = req.session.user; above and req.session.user gets set when my route /login is hit and here is it's code.
login.js
var express = require('express');
var router = express.Router();
var User = require('../models/user.model.js');
var app = require('../app');
/* GET signup page. */
router.get('/', function(req, res, next) {
res.render('login');
});
router.post('/', function(req, res, next) {
User.findOne({
email: req.body.email
}, function(err, user) {
var logged = false;
if (err) {
console.log(err);
} else if (!user) {
res.render('login', {
errnoacc: 'User does not exist! Please register.'
})
} else if (user && req.body.password == user.password) {
req.session.user = user;
res.render('dashboard');
} else {
res.render('login', {
errpass: 'Password does not match. Please try again!'
});
}
});
next();
});
module.exports = router;
In the above code when POST is hit, I assign req.session.user = user; if all is good I render the dashboard view, there are a layout.hbs which has navbar where I want to use app.locals.currentUser to show currentUser object.
Using in my layouts.hbs {{currentUser.username}} doesn't work.
I am new to expressjs development so I know I am missing something.
app.locals holds settings for all application, if you app gets more than one user it will overwrite the information.
app.use(function(req, res, next) {
app.locals.currentUser = req.session.user;
next();
});
You may use res.locals:
app.use(function(req, res, next){
res.locals.user = req.user;
res.locals.authenticated = ! req.user.anonymous;
next();
});
Then you can access in handlebar like:
p #{user.userName}

Express Js: Router.use() Requires Middleware function

I am developing an application in Express Js. When I try to run the application I get this error:
My app.js file is like this:
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 app = express();
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: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
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);
});
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
});
});
}
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var server = app.listen(3000, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
module.exports = router;
My index.js is like this:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index', {title: 'Polls'});
});
router.get("/list", function (req, res, next) {
Poll.find({}, 'question', function (error, polls) {
res.json(polls);
});
});
router.get("/poll", function (req, res, next) {
var pollId = req.params.id;
// Find the poll by its ID, use lean as we won't be changing it
Poll.findById(pollId, '', {lean: true}, function (err, poll) {
if (poll) {
var userVoted = false,
userChoice,
totalVotes = 0;
// Loop through poll choices to determine if user has voted
// on this poll, and if so, what they selected
for (c in poll.choices) {
var choice = poll.choices[c];
for (v in choice.votes) {
var vote = choice.votes[v];
totalVotes++;
if (vote.ip === (req.header('x-forwarded-for') || req.ip)) {
userVoted = true;
userChoice = {_id: choice._id, text: choice.text};
}
}
}
// Attach info about user's past voting on this poll
poll.userVoted = userVoted;
poll.userChoice = userChoice;
poll.totalVotes = totalVotes;
res.json(poll);
} else {
res.json({error: true});
}
});
});
router.get("/create", function (req, res, next) {
var reqBody = req.body,
// Filter out choices with empty text
choices = reqBody.choices.filter(function (v) {
return v.text != '';
}),
// Build up poll object to save
pollObj = {question: reqBody.question, choices: choices};
// Create poll model from built up poll object
var poll = new Poll(pollObj);
// Save poll to DB
poll.save(function (err, doc) {
if (err || !doc) {
throw 'Error';
} else {
res.json(doc);
}
});
});
module.exports = router;
And user.js is this:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
I tried to find my solution on SO, but couldn't. Feel free to tell me if i need to provide any other file. Any help?
You should define routes in your index.js like you do in user.js.
app.use('/', routes) in your code expects routes to be an instance of a Router, but you're exporting an object with functions instead of that.
So your index.js file should have the following structure:
var express = require('express');
var router = express.Router();
router.get("/", function (req, res) {
res.render('index');
});
router.get("/list", function(req, res) {/*list implementation*/});
....
module.exports = router;

How to properly apply routes inside another file

I'm fairly new to express js and I want to know how to use router. I created a file named categories.js inside routes directory with this code.
categories.js code:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/categories', function(req, res) {
res.send('this is the category');
});
module.exports = router;
inside the app.js i have this code:
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 categories = require('./routes/categories');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');
// uncomment after placing your favicon in /public
//app.use(favicon(__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('/', routes);
app.use('/users', users);
app.use('/categories', categories);
// 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;
I have tried understand what is wrong but i can't see to figure out. thanks in advance.
This is the error im getting
Not Found
404
I will like to add inside the routes directory i have a index.js file and this one works.
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
I think my application is not reading the categories.js file, because when I put the category.js code inside index.js it works. but it doesn't work if i put it in a separate file in my case category.js.
I think you've got your categories route hooked up wrong, your categories are mapped to /categories/categories in your code. To fix it, try this in your app.js:
app.use('/', categories);
If you don't want to prefix, you can also simply do this:
app.use(categories);

Categories