Internal q TypeError on node-express server
jQrgen opened this issue · comments
Hello
I'm using q in my express-node server.
For some reason q crases with a TypeError when I GET the endpoint GET_nearbyTesters.
There is no stack trance from q to within my project, the stack trace ends in the q library folder
/app/node_modules/q/q.js:155
throw e;
^
TypeError: Cannot read property 'app' of undefined
at json (/app/node_modules/express/lib/response.js:246:17)
at _rejected (/app/node_modules/q/q.js:864:24)
at /app/node_modules/q/q.js:890:30
at Promise.when (/app/node_modules/q/q.js:1142:31)
at Promise.promise.promiseDispatch (/app/node_modules/q/q.js:808:41)
at /app/node_modules/q/q.js:624:44
at runSingle (/app/node_modules/q/q.js:137:13)
at flush (/app/node_modules/q/q.js:125:13)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
Route that triggers the crash (GET_nearbyTesters):
const router = require('express').Router();
const middleware = require('../middleware.js');
router.get('/', function (req, res, next) {
middleware.getUsers(req)
.then(function () {
next();
})
.catch(res.json)
.done();
}, function(req, res, next) {
middleware.getNearbyUsers(req, res)
.then(function () {
next();
})
.catch(res.json)
.done();
});
module.exports = router;
Middleware for the GET_nearbyTesters route
const calculate = require('./services/calculate.js');
const Q = require('q');
const firebase = require('firebase-admin');
const isDefined = require('./services/calculate').isDefined;
const ref = firebase.database().ref();
const middleware = {
// Binds usersSnap to req object
getUsers: (req) => {
const deferred = Q.defer();
ref.child('users').once('value')
.then((usersSnap) => {
req.usersSnap = usersSnap;
deferred.resolve(usersSnap.val());
})
.catch((error) => {
deferred.reject(error);
});
return deferred.promise;
},
// Requires usersSnap being bound to req object.
getNearbyTesters: function (req, res) {
const deferred = Q.defer();
const usersSnap = req.usersSnap;
const userID = req.query.userID;
const centerUser = usersSnap.child(userID);
const nearbyTesters = [];
let distance;
if(isDefined(usersSnap)){
usersSnap.forEach((userSnap) => {
if(centerUser.key !== userSnap.key && userSnap.val().testMode){
try {
distance = calculate.distance(userSnap.val().lat, userSnap.val().long, centerUser.val().lat, centerUser.val().long, 'K');
} catch(error){
deferred.reject(error);
}
if(distance <= 1000){
nearbyTesters.push(userSnap.val().facebook.uid);
}
}
});
res.type('json');
res.status(200).json({ nearbyTesters: nearbyTesters });
deferred.resolve(nearbyTesters);
res.end();
}else {
deferred.reject(new Error('req.usersSnap is undefined'));
}
return deferred.promise;
}
};
index.js just in case:
var app = require('express')(),
bodyParser = require('body-parser'),
path = require('path'),
serviceAccount = require(path.resolve(__dirname, process.env.firebase_service_account_path)),
firebaseAdmin = require('firebase-admin');
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: process.env.firebase_url
});
// Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.json() );
app.use(bodyParser.urlencoded({ extended: false }));
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use('/GET_nearbyUsers', require('./routes/GET_nearbyUsers.js'));
app.use('/GET_nearbyTesters', require('./routes/GET_nearbyTesters.js')); // The route in question
app.use('/POST_sendVerifySMS', require('./routes/POST_sendVerifySMS.js'));
app.use('/POST_backgroundLocation', require('./routes/POST_backgroundLocation.js'));
app.use(function (error, req, res, next) { // eslint-disable-line
console.error(error);
res.status(500).send(error);
});
// Start node server
app.set('port', (process.env.PORT || 1339 || 2000));
app.listen(app.get('port'), () => {
console.log('Node app is running on port', app.get('port'));
});
require('./firebase-observers.js').init();
package.json just in case:
{
"name": "flare_sms",
"version": "1.0.0",
"main": "app/index.js",
"dependencies": {
"body-parser": "1.17.1",
"express": "4.15.2",
"firebase": "^4.2.0",
"firebase-admin": "^5.1.0",
"q": "^1.5.0",
"speakeasy": "2.0.0",
"twilio": "^2.11.1",
"util": "^0.10.3"
},
"devDependencies": {
"chai": "^4.1.1",
"chai-as-promised": "^7.1.1",
"eslint": "^3.17.1",
"eslint-plugin-mocha": "^4.11.0",
"express-mocks-http": "0.0.11",
"firebase-mock": "^1.1.5",
"foreman": "^2.0.0",
"istanbul": "^0.4.5",
"mocha": "^3.5.0",
"node-mocks-http": "^1.6.4",
"nodemon": "^1.11.0",
"nyc": "^11.1.0",
"proxyquire": "^1.8.0",
"supertest": "^3.0.0",
"tap-spec": "^4.1.1"
},
"scripts": {
"test": "./node_modules/.bin/mocha -w",
"test-api": "node test/index.tutorial | tap-spec",
"start": "nf start",
"watch": "foreman run nodemon --watch ./"
},
"engines": {
"node": "6.11.1"
},
"author": "Flare"
}
Thanks for any help.
The issue seems to be unrelated to q and instead related to error handling in my node-express server.