This is similar to this question, but my code has multiple routes.
The code works below for what I want to do, but I want to know if there's a cleaner way to write it as I'm fairly new to Node/Express/Redis.
var express = require('express');
var router = express.Router();
var io = require('socket.io');
var redis = require('./../lib/redis');
redis.get('count', function(err, value) {
if(err) throw err;
/* GET Dashboard */
router.get('/', function(req, res) {
res.render('dashboard', {title: 'Data Dashboard', count: value });
});
/* GET Backend */
router.get('/backend', function(req, res) {
res.render('backend', {title: 'Backend', count: value });
});
});
module.exports = router;
Basically, I'm just passing a single Redis key-value to both of my routes.
Any suggestions to clean it up are appreciated.
The way your code is written you'll be passing the same value of the count key for your whole application life-cycle. There's nothing wrong with the code from a cleaning up perspective, but from a service point of view, the routes shouldn't be within the REDIS GET callback.
Getting the value within the route
// Use everytime you need to count the key
function redisCount = function(callback) {
redis.get('count', function(err, value) {
if(err) callback(err)
callback(null, value)
}
}
/* GET Dashboard */
router.get('/', function(req, res) {
redisCount(function(err,value) {
if(err) throw err;
res.render('dashboard', {title: 'Data Dashboard', count: value });
})
});
/* GET Backend */
router.get('/backend', function(req, res) {
redisCount(function(err,value) {
if(err) throw err;
res.render('backend', {title: 'Backend', count: value });
})
});
However if you do this count call for absolutely every single route, I would suggest a piece of middleware that just sets value into the context for every call:
Getting the value in a separate middleware
app.use(function (req, res, next) {
// using the same function for the redis count
redisCount(function(err, value) {
// respond with error
if (err) res.status("Could not connect to Redis")
// otherwise set the value in the session
req.session.value = value
// and move on to the next middleware
next()
});
});
// now simply declare your routes
/* GET Dashboard */
router.get('/', function(req, res) {
res.render('dashboard', {title: 'Data Dashboard', count: req.session.value });
});
/* GET Backend */
router.get('/backend', function(req, res) {
res.render('backend', {title: 'Backend', count: req.session.value });
});
Related
I am currently trying to test an application with Mocha and Chai but I am having difficulties in connecting one of the modules to the test.
Here is my test case:
"use strict";
var chai = require('chai');
var expect = require("chai").expect;
var helloWorld = require("../routes");
var mongoose = require("mongoose");
var app = require("../app");
var application = require("../routes");
describe('helloWorld', function () {
it('Mongo Module extended', function () {
expect(helloWorld()).equal('Mongo Module Extended');
});
});
describe('application', function application(app){
it('connects properly', function(done) {
expect(application(app))
.request('http://localhost:80')
.get('/')
.end(function(err, res) {
expect(res).to.have.status(200);
done(); // <= Call done to signal callback end
});
});
});
and here is the file I am currently trying to test:
var passport = require('passport');
var Account = require('./models/account');
var path = require('path');
var mongojs = require('mongojs');
var dbx = mongojs('test', ['logs']);
var fs = require('fs');
var dbc = mongojs('test', ['accounts']);
function helloWorld() {
return 'Mongo Module Extended';
}
module.exports = helloWorld;
function application(app) {
app.get('/',
function(req, res){
res.sendFile('login.html', {root: __dirname});
});
app.get('/login',
function(req, res){
res.sendFile(path.join(__dirname + '/login.html'));
});
app.get('/index', isLoggedIn,
function(req, res){
req.flash('info', 'Flash is back!')
res.sendFile(path.join(__dirname + '/views/index.html'));
});
app.get('/', isLoggedIn,
function(req, res){
res.sendFile(path.join(__dirname + '/login.html'));
});
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.json({success:false, message: "Wrong Username or Password"}); //sends json message to the Front end jQuery function
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
res.json({success:true, redirectTo: '/index', message: "You are logged-in."}); //sends json message to the Front end jQuery function
/* Add username and time of login to the collection in MongoDB */
dbc.accounts.findOne(function(err, info){
var users = info.username; //Gets the logging username from the collection
var date = new Date().toLocaleDateString(); // generates a new date.
console.log(date);
console.log(date +" "+ "date");
var stamp = {name: users, time:date}; // object to hold both variables.
//toLocaleDateString('en-GB')
dbx.logs.insert(stamp, function(err, result){ //query to insert one inside the "logs" collection.
if(err) { throw err; }else{console.log("added" + JSON.stringify(stamp));}
});
});
/* END of Collection Logging Method */
});
})(req, res, next);
});
app.get('/logout',
function(req, res){
req.logout();
res.redirect('/login');
});
function isLoggedIn(req, res, next) {
//console.log('here is Authenticated', req.isAuthenticated()) //prints out 'here is Authenticated' if the Passport login is successful
if (req.isAuthenticated()){
console.log('here is Authenticated');
return next();
}else{
console.log("you cannot access the routes without being logged in!");
}
}
module.exports = application;
I keep receiving this error:
TypeError: expect(...).request is not a function
which I guess is referencing the first get request I am trying to make in my application file:
app.get('/',
function(req, res){
res.sendFile('login.html', {root: __dirname});
});
At this point I am not really sure how to fix this. I know that my error is in the way that I am trying to test the get request but I cannot seem to bypass it.
How can I correct my code so I can reference the methodsGET and POST methods from module.exports = application; correctly?
Chai on its own doesn't support testing of http routes, you need chai-http to do just that.
You could see the link for more: https://scotch.io/tutorials/test-a-node-restful-api-with-mocha-and-chai
I am very new to node js. I have made an application, where when admin logs in, it is showing 'Cannot POST /userslist', but once I refresh the page, it is fetching the userslist, following is the routing code for admin-
admin.js-
module.exports = function(app)
{
app.get('/adminedit', function (req, res) {
res.render('adminedit', { });
});
app.get('/userslist', function (req, res) {
res.render('userslist', { });
});
}
i think the best way to achieve your goal (using express) is:
create a single service (called for example listUsers) in this way:
var express = require('express');
var router = express.Router();
router.post('/', function(req, res, next) {
User.find(function (err, users) {
if(err) return res.json({success: false, message: err});
res.json({success: true, userlist: users});
)};
});
module.exports = router;
then you can use this service in app.js in this way:
var userListService = require('./routes/listUsers');
app.use('/listUsers', userListService);
at this point if you try to call in POST /listUsers, everything should work fine.
Background:
I'm writing my first MEAN application. I'm trying to create an API that allows basic CRUD ops on a collection called "chassis".
Problem
So far, i can GET all records using find(). I can also findById, and update existing records, no problems.
However, when I try to POST, I get the following error:
dev#devbox:~/nimble_express/nimbleApp$ curl -X POST localhost:3000/chassis/ -d name=widget123 -d location=Canada -d ffd=test123 -d hw_model=hp -d asset_tag=12344
<h1>document must have an _id before saving</h1>
<h2></h2>
<pre>Error: document must have an _id before saving
at null._onTimeout (/home/dev/nimble_express/node_modules/mongoose/lib/model.js:112:18)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)</pre>
dev#devbox:~/nimble_express/nimbleApp$
Code
I have the following logic in a routes/chassis.js file:
var express = require('express');
var router = express.Router();
//var mongoose = require('mongoose');
var Chassis = require('../models/Chassis.js');
/* GET chassis listing. */
router.get('/', function(req, res, next) {
Chassis.find( function(err, documents) {
if (err) return next(err);
res.json(documents);
});
});
/* GET /chassis/id */
router.get('/:id', function(req, res, next) {
Chassis.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* POST /chassis */
router.post('/',function(req, res, next) {
console.log(req);
Chassis.create(req.body, function(err, post) {
if (err) return next(err);
res.json(post);
});
});
/* UPDATE /chassis/id */
router.put('/:id', function(req, res, next) {
Chassis.findByIdAndUpdate(req.params.id, req.body, function(err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
~
I've tried googling for this error but haven't found anything too useful yet.
Any pointers would be helpful and appreciated!
I am trying to write a code for user login authentication in express using express-session
This is my accounts.js api
.use(bodyParser.urlencoded())
.use(bodyParser.json())
.use(session({ secret: 'hcdjnxcds6cebs73ebd7e3bdb7db73e' }))
.get('/login', function (req, res) {
res.sendfile('public/login.html');
})
.post('/login', function (req, res) {
var user = {
username : req.body.username,
password : hash(req.body.password)
};
var collection = db.get('users');
collection.findOne (user, function (err, data) {
if (data) {
req.session.userId = data._id;
res.redirect('/');
} else {
res.redirect('/login');
}
});
})
.get('/logout', function (req, res) {
req.session.userId = null;
res.redirect('/');
})
.use(function (req, res, next) {
if (req.session.userId) {
var collection = db.get('users');
collection.findOne({ _id : new ObjectId(req.session.userId)}, function (err, data) {
req.user = data;
});
}
next();
});
module.exports = router;
And this is my server.js code
var express = require('express'),
api = require('./api'),
users = require('./accounts'),
app = express();
app
.use(express.static('./public'))
.use('/api', api)
.use(users)
.get('*', function (req, res) {
if (!req.user) {
res.redirect('/login');
} else {
res.sendfile(__dirname + '/public/main.html');
}
})
.listen(3000);
My problem is, in server.js, req.user is getting null value that's why i am not able to login. But in account.js req.user getting user data which is not reflecting in server.js.
Again, if in accounts.js, I am placing next() inside the if (req.session.userId) statement, I am able to get user data in server.js but it creating problem in logout.
Please help me out in this.
Your accounts.js is executing next() before your collection query returns, so it makes sense that your req.user is undefined in your middleware later on. To fix it, try this:
.use(function (req, res, next) {
if (req.session.userId) {
var collection = db.get('users');
collection.findOne({ _id : new ObjectId(req.session.userId)}, function (err, data) {
req.user = data;
next();
});
} else {
next();
}
});
As a side note, you're very much reinventing the wheel here by implementing user login yourself. I would reccommend taking take a look at passportjs for doing user login like this.
I'm using express 4.9.0.
I have the following code in my user.js file inside route folder.
/* Get User by id. */
router.get('/:id', function(req, res) {
console.log('find user ' + req.params.id);
User.findById(req.params.id, function (err, user) {
if (!err) {
return res.send(user);
}
return console.log(err);
});
});
Later, in app.js:
app.use('/users', users);
However, when i navigate to http://localhost:3000/users?id=546e5640f5fea84a345abe2c the route is never hit. Calls to other routes work fine.
What am I doing wrong?
For the route you currently have, you'd need to make your request url this: /users/546e5640f5fea84a345abe2c.
If you want your route to match the request url you're currently trying (/users?id=546e5640f5fea84a345abe2c), then you would instead do:
/* Get User by id. */
router.get('/', function(req, res) {
console.log('find user ' + req.query.id);
User.findById(req.query.id, function (err, user) {
if (!err) {
return res.send(user);
}
return console.log(err);
});
});