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.
Related
The server.js code is this one after running the node server.js command
i am able to access the http://localhost:8080/ and getting the json correctly
{"error":false,"data":[{"id":1,"task":"Find bugs","status":1,"created_at":"2016-04-10T18:20:40.000Z"},{"id":2,"task":"Review code","status":1,"created_at":"2016-04-10T18:20:40.000Z"},{"id":3,"task":"Fix bugs","status":1,"created_at":"2016-04-10T18:20:40.000Z"},{"id":4,"task":"Refactor Code","status":1,"created_at":"2016-04-10T18:20:40.000Z"},{"id":5,"task":"Push to prod","status":1,"created_at":"2016-04-10T18:20:50.000Z"}],"message":"Todos list."}
but when i try to access the http://localhost:8080/secret i am getting "Cannot GET /secret " error. My server.js file is this one
const express = require('express');
const app = express();
const mysql = require('mysql');
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended:true
}));
const mc = mysql.createConnection({
host:'localhost',
user : 'root',
password : '',
database : 'task'
});
mc.connect();
// Retrieve all todos
//default route
app.all('/',function(req,res,next){
mc.query('SELECT * FROM tasks', function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results, message: 'Todos list.' });
next()
});
});
app.use('/secret', function (req, res, next) {
console.log('Accessing the secret section ...')
next() // pass control to the next handler
})
app.listen(8080,function(){
console.log('Node app is running on port 8080');
});
Any help will be much appreciated
Your implementation right now seems incomplete. You should check out the express.Router documentation (check out the very bottom of the page).
The use method you are trying to use should include at least a router.get('/', function (req, res) {} ); implementation. Alternatively, you could replace use with get or all and it would work.
Good luck!
You should use get instead of all, and the next function is not required. try the below method.
app.get('/', function (req, res) {
mc.query('SELECT * FROM tasks', function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results, message: 'Todos list.' });
});
});
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 building an API backend with Express (v4) and facing an issue that my middleware function is not called
on sub-paths of my route. E.g. it is called for /movie but not for /movie/search.
I have split my routes into separate files. Below is the code, shortened to the relevant parts.
Any help is appreciated!
app.js
var express = require('express');
var app = express();
var router = require('routes')(app);
/routes/index.js
module.exports = function(app) {
app.use('/movie', check_authentication, require('movie'));
};
/routes/movie.js
var Movie = require(../models/movie');
// Middleware is working for this route (/movie?movie_id=123)
router.get('/', function(req, res) {
Movie.findById(req.query.movie_id)
.then(function(movie) {
res.status(200).json(movie);
}, function(err) {
res.status(400).send(err);
});
});
// Middleware is NOT working for this route (/movie/search?keyword=matrix)
router.get('/search', function(req, res) {
Movie.findById(req.query.keyword)
.then(function(movie) {
res.status(200).json(movie);
}, function(err) {
res.status(400).send(err);
});
});
/routes/check_authentication.js
var express = require('express');
var router = express.Router();
var firebaseAdmin = require('firebase-admin');
var path = require('path');
var config = require(path.resolve(__dirname, '../config/config.json'));
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(path.resolve(__dirname, '../config/' + config.firebase.serviceAccount)),
databaseURL: config.firebase.databaseURL
});
// AUTHENTICATION MIDDLEWARE
// needs to be included in any request which requires authorization
// =============================================================================
router.all('/', function(req, res, next) {
// check if authorization header is present
var token = req.headers['authorization'];
if (typeof token === 'undefined') {
res.status(403).json({ Error: 'Unauthenticated' });
}
else {
firebaseAdmin.auth().verifyIdToken(token).then(function(decodedToken) {
req.email = decodedToken.email;
next(); // all good. go ahead with the request
}).catch(function(error) {
res.status(403).json({ Error: 'Unauthenticated' });
});
}
});
module.exports = router;
It seems I found the problem.
Changing the middleware to trigger on * fixes it.
router.all('*', function(req, res, next)
Maybe someone can confirm that this is the way to go.
The check_authentication module should export the middleware function, not a router.
module.exports = function(req, res, next) {
// check if authorization header is present
// ...
});
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.
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 });
});