I have a middleware setup in node to perform a task and call next upon success or failure. The task is called after an initial promise block runs. It is called in the .then function:
var Q = require('q');
var dataPromise = getCustomerId();
dataPromise
.then(function(data) {
getGUID(req, res, next);
}, function(error) {
console.log('Failure...', error);
});
};
The server hangs though because the (req,res,next) parameters are all undefined when in the context of the .then function.
Here is getCustomerId function:
var getCustomerId = function() {
var getCustomerIdOptions = {
options...
};
var deferred = Q.defer();
request(getCustomerIdOptions, function(err,resp,body){
if(err){
deferred.reject(err);
console.log(err);
return;
}else{
deferred.resolve(body);
}
});
return deferred.promise;
};
What would be the correct way to pass these parameters to the function called in the .then block?
EDIT:
The (req,res,next) parameters are from the outer function and are accessible when getGUID(req,res,next) is called outside of the .then() block.
var assureGUID = function(req, res, next) {
if(app.locals.guid){
next();
return;
}
var dataPromise = getCustomerId();
dataPromise
.then(function(data) {
getGUID(req, res, next)
}, function(error) {
console.log('Failure...', error);
}).;
};
Not sure what you are trying to do exactly, but you can call your promise function inside a express common middleware function like the next sample.
var express = require('express');
var $q = require('q');
var request = require('request');
var app = express();
// Middleware 1
app.use( function(req, res, next) {
console.log('i\'m the first middleware');
getCustomerId().then( function(body) {
console.log('response body', body);
return next();
},
function(err) {
console.log('Error on middlware 1: ', err);
});
});
// Middleware 2
app.use( function(req, res, next) {
console.log('i\'m the second middleware');
return next();
});
app.get('/', function(req, res) {
res.send('hi world');
});
app.listen(3000);
// Your custom function definition
function getCustomerId() {
var deferred = $q.defer();
request('http://someurltogetjsondata/user/id', function(err, resp, body) {
if(err) return deferred.reject(err);
deferred.resolve(body);
});
return deferred.promise;
}
I hope this helps a little, good luck.
Related
I have post.route.js where I mention
var post = require('../controllers/post.controller');
router.route('/posts').get(post.getPosts, post.setCache);
and my post.controller.js has the
exports.getPosts = function(req, res, next) {
var qstring = postQueryString;
getPostsDataByQuery(qstring,req,res,next);
}
function getPostsDataByQuery(queryString,req, res, next){
logger.info('start',req.route.path);
// some code here
return res.json(rows);
next();
};
exports.setCache = function(req, res, next){
console.log('here in set function');
cache.setExp(req, rows);
return true;
}
if in the setExp I log the not showing me
exports.setExp = function(req, data){
console.log('here');
}
You could make use of the next method:
function getPosts(queryString, req, res, next){
// your code
next();
};
function setCache(req, res) {
cache.setExp(req.originalUrl, process.env.CACHE_POST_EXP_TIME, rows);
return true;
}
router.route('/posts').get(post.getPosts, post.setCache);
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
In below example for GET /api/users/i request secondMw is never executed even there is a next() call in firstMw. Why is that? How am I supposed to be able to run the secondMw?
var apiRouter = require('express').Router();
apiRouter.param('user', function firstMw(req, res, next, param) {
if(param === 'i'){
return next(); //jump to next mw sub-stack
}
next('route'); //continue with another matching route
}, function secondMw(req, res, next, param) {
console.log('NO, I AM NOT HERE. NEVER');
next();
});
apiRouter.get('/users/:user', function (req, res, next) {
res.json({
id: req.params.user
});
});
app.use('/api', apiRouter);
I don't see that router.params supports middleware stack (compare definition with app.get). But you can use ordered definition for same route.
'use strict';
let express = require('express');
let app = express();
app.use(require('body-parser').urlencoded({extended: false}));
var apiRouter = express.Router();
apiRouter.param('user', function mw1(req, res, next, param) {
console.log('MW1', param);
if (param === 'i')
next();
else
next('Error message'); // better next( new Error('Error message'));
});
apiRouter.param('user', function mw2(req, res, next, param) {
console.log('MW2', param);
next();
})
// If next() have params then Express calls handler error
apiRouter.use(function (err, req, res, next) {
console.log('Error: ', err)
res.send(err.message || err);
});
apiRouter.get('/users/:user', function (req, res, next) {
res.json({id: req.params.user});
});
app.use('/api', apiRouter);
app.listen(3000, function () {
console.log('Listening on port 3000');
});
This is app have only GET /test, it doesn't have POST /test yet. I'm uploading binary file 1.dat to it and it should return answer with '404', but seems I'm recieving ECONNRESET error instead.
var express = require('express');
var app = express();
var expect = require('expect.js');
var request = require('supertest');
var router = express.Router({
caseSensitive: true,
strict: true
});
router.get('/', function(req, res, next) {
res.send('test');
});
app.use('/test', router);
app.use(function(req, res, next) {
res.send('404');
});
Promise.resolve().then(function() {
var agent = request(app);
return new Promise(function(resolve, reject) {
agent
.get('/test')
.expect(200)
.end(function(err) {
if (err) {
return reject(err);
}
resolve(agent);
});
});
}).then(function(agent) {
return new Promise(function(resolve, reject) {
agent
.post('/test')
.attach('tmp', new Buffer([1, 2, 3]), '1.dat')
.expect(404)
.end(function(err, res) {
if (err) {
return reject(err);
}
resolve();
});
});
}).then(function() {
process.exit(0);
}).catch(function(err) {
console.log(err.stack);
process.exit(1);
});
But why it throws an error when validating .expect(404):
[TypeError: Cannot read property 'status' of undefined]
You don't send a status 404 but a string in your body.
app.use(function(req, res, next) {
res.status(404).end();
});
In a practice example, i'm trying to create a restfull API, very simple. The plain GET and POST methods works well, but the GET, PUT and DELETE method pointing to /api/bears/:bear_id just stay there, waiting...
// CONFIGURACION INICIAL //
// ===================== //
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var db = mongoose.connection;
// CONFIGURANDO APP //
// ================ //
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
mongoose.connect('mongodb://localhost:27017/bears');
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function cb () {
console.log('conexion establecida');
})
var Bear = require('./models/bear_model.js');
var port = process.env.PORT || 8080; // seteo del puerto
var router = express.Router(); // instancia del ruteador
Above, the simple config, below, the snippet that is causing me problems:
router.use(function (req, res, next) { // simple logger
if (req.method === 'GET')
console.log('executing query on id %s', JSON.stringify(req.params));
else if (req.method === 'PUT')
console.log('executing query on id %s', JSON.stringify(req.params));
else
console.log('executing query on id %s', JSON.stringify(req.params));
});
router.route('/bears/:bear_id')
.get(function (req, res) {
Bear.findById(req.params.bear_id, function (err, bear) {
if (err)
res.send(err);
res.json(bear);
});
}) // end GET /bears/:bear_id
.put(function (req, res) {
Bear.findById(req.params.bear_id, function (err, bear) {
if (err)
res.send(err)
bear.name = req.body.name; // Update bear_id of Bear
bear.save(function (err) {
if (err)
res.send(err);
res.json({msg: 'Bear actualizado!'});
});
});
}) // end PUT /bears/:bear_id
.delete(function (req, res) {
Bear.remove({
_id: req.params.bear_id
}, function (err, bear) {
if (err)
res.send(err);
res.json({ msg: 'Bear eliminado' });
});
}); // end DELETE /bears/:id && router /bears/:id
app.use('/api', router); // la api usarĂ¡ como base el prefijo /api
Executing one route with a param log me: executing query on {}, so, the req.params.bear_id simply is not captured, and if i change req.params by req.params.bears_id, obviously i get an undefined log, so i read de docs and think i'm doing generally well the process but don't catch the issue.
You are not calling next() in your logger, so you're never getting to your router, which results in no response.
router.use(function (req, res, next) { // simple logger
if (req.method === 'GET')
console.log('executing query on id %s', JSON.stringify(req.params));
else if (req.method === 'PUT')
console.log('executing query on id %s', JSON.stringify(req.params));
else
console.log('executing query on id %s', JSON.stringify(req.params));
next();
});
Now the reason you are not seeing params in your logger is because params are only visible if the route definition has params. Your logger middleware doesn't define a specific route, therefore there are no params. A solution to this would be to use Router.param
router.param('bear_id', function(req, res, next, bear_id) {
if (req.method === 'GET')
console.log('executing query on id ' + bear_id);
else if (req.method === 'PUT')
console.log('executing query on id ' + bear_id);
else
console.log('executing query on id ' + bear_id);
next();
});
More simply:
router.param('bear_id', function(req, res, next, bear_id) {
console.log(req.method + ' with id ' + bear_id);
next();
});
This works this way by design, you can find more information on github:
https://github.com/strongloop/express/issues/2088