MemoryStore in node.js - node.js

I am working on implementing social network application using node.js and the source that I use is Building Node Application with MongoDB and Backbone' by Mike Wilson.However, I cannot figure out the how to resolve the error of the MemoryStore --var MemoryStore = require('connect').session.MemoryStore;
Also, I tried to comment it but the error with middleware appear
var Session = require('connect').middleware.session.Session;
Can I get your help please ?
Thanks in advance
Here is the code of app.js
var express = require('express');
var http = require('http');
var app = express();
var nodemailer = require('nodemailer');
var MemoryStore = require('connect').session.MemoryStore;
var dbPath = 'mongodb://10.168.122.123:27017/socialnet';
var fs = require('fs');
var events = require('events');
// Create an http server
app.server = http.createServer(app);
// Create an event dispatcher
var eventDispatcher = new events.EventEmitter();
app.addEventListener = function (eventName, callback) {
eventDispatcher.on(eventName, callback);
};
app.removeEventListener = function (eventName, callback) {
eventDispatcher.removeListener(eventName, callback);
};
app.triggerEvent = function (eventName, eventOptions) {
eventDispatcher.emit(eventName, eventOptions);
};
// Create a session store
app.sessionStore = new MemoryStore();
// Import the data layer
var mongoose = require('mongoose');
var config = {
mail: require('./config/mail')
};
// Import the model
var models = {
Account: require('./models/Account')(app, config, mongoose, nodemailer)
}
// Configure the application
app.configure(function(){
app.sessionSecret = 'SocialNet secret key';
app.set('view engine', 'jade');
app.use(express.static(__dirname + '/public'));
app.use(express.limit('1mb'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
secret: app.sessionSecret,
key: 'express.sid',
store: app.sessionStore
}));
mongoose.connect(dbPath, function onMongooseError(err) {
if (err) throw err;
});
});
// Import the routes located in ./routes
fs.readdirSync('routes').forEach(function(file) {
if (file[0] == '.') return;
var routeName = file.substr(0, file.indexOf('.'));
require('./routes/' + routeName)(app, models);
});
// -----
// GET /
// -----
app.get('/', function(req, res){
res.render("index.jade", {layout: false});
});
// -------------------
// POST /contacts/find
// -------------------
app.post('/contacts/find', function(req, res) {
var searchStr = req.param('searchStr', null);
if (null == searchStr) {
res.send(400);
return;
}
models.Account.findByString(searchStr, function onSearchDone(err, accounts) {
if (err || accounts.length == 0) {
res.send(404);
} else {
// TODO: Check if these accounts were already contacts
// if so, mark them as isContact so the views/Contact
// knows not to add a addButton
res.send(accounts);
}
});
});
// Let the server listen to 8000 (instead of the app)
app.server.listen(8000);
console.log('SocialNet listening to port 8000');

Your problem:
app.use(app.router)
, mounts your routes in that position in the call chain. You have it before your session middleware, so there is no req.session yet. When you leave it out, your routes will be positioned whenever you do your first app.get (or app.post and so on). If you still wish to control where your routes should be,
you can just:
move app.use(app.router) below the session middleware.

Related

How do I modularize my Node.js, express project?

I have created a API for different webpages with some CRUD functionality for POST, GET, etc. methods using Node.js, express and mongoose. I also have a big app.js file, where my routing logic and functions for CRUD methods reside.
So in the app.js file, I have to do the CRUD functionality and routing logic for every model in my models folder. This is quite much for on file, how can I separate the CRUD logic for my models, and the routing logic? So that it still works as normal without hosing my file?
I was thinking to separate the CRUD into a "controllers" folder and the routing into the "routes" folder, but I dont know how exactly, and what to require at what place..
My app.js looks like:
var express = require('express');
var app = express();
var bodyParser = require("body-parser");
var morgan = require("morgan");
var routes = require('./routes');
var cors = require('cors')
//configure app
app.use(morgan('dev')); //log requests to the console
//configure body parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = process.env.PORT || 5000;
//DATABASE SETUP
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/DNZ'); //connect to uor datbaase
//Handle the connection event, get reference to database.
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("DB connection alive");
});
//DNZ models live here
var FA = require('./models/DNZmodels/FA');
var FP = require('./models/DNZmodels/FP');
//ROUTES FOR OUR API
//=============================================================================
//create our router
var router = express.Router();
//middleware to use for all requests
router.use(function(req, res, next) {
// do logging
console.log('Something is happening.');
console.log('Today is:', Date())
next();
});
//test route to make sure everything is working (accessed at GET http://localhost:5000/DNZ/)
router.get('/', function(req, res) {
res.json({ message: 'Welcome to DNZ API!' });
});
//on routes that end in /FA
//----------------------------------------------------
router.route('/FA')
// create a FA (accessed at POST http://localhost:8080/DNZ/FA)
.post(function(req, res) {
//console.log(req.body);
//console.log(req.body.params);
//res.setHeader('Content-Type', 'application/json')
//res.send(JSON.stringify(req.body));
/*
var timestamp = req.body.Timestamp;
var prognostizierterBetriebswert = req.body.PrognostizierterBetriebswert;
var posFlexPot = req.body.posFlexPot;
var negFlexPot = req.body.negFlexPot;
var leistungsuntergrenze = req.body.Leistungsuntergrenze;
var leistungsobergrenze = req.body.Leistungsobergrenze;
var posGesEnergie = req.body.posGesEnergie;
var negGesEnergie = req.body.negGesEnergie;
var preissignal = req.body.Preissignal;
var dummy1 = req.body.Dummy1;
var dummy2 = req.body.Dummy2;
var dummy3 = req.body.Dummy3;
var fa = new FA({
Timestamp: timestamp,
Leistungsuntergrenze: leistungsuntergrenze,
Leistungsobergrenze:leistungsobergrenze,
PrognostizierterBetriebswert :prognostizierterBetriebswert,
posFlexPot: posFlexPot,
negFlexPot:negFlexPot,
posGesEnergie: posGesEnergie,
negGesEnergie: negGesEnergie,
Preissignal:preissignal,
Dummy1: dummy1,
Dummy2: dummy2,
Dummy3: dummy3
})
*/
//fa.name = req.body.name;
console.log("Erzeugen der Instanz FA..");
//console.log(Dummy1);
//res.send(JSON.stringify(timestamp));
// create a new instance of the FA model
var fa = new FA(req.body);
//SAVE the new instance
fa.save(function(err) {
if (err) {
console.log(err);
res.status(400);
res.send(err);
}
else {
console.log("Instanz FA in Datenbank erzeugt!");
res.status(200);
res.json({ message: 'FA-Instance created in datbase!' });
}
});
})
// get all the FAs (accessed at GET http://localhost:8080/DNZ/FA)
.get(function(req, res) {
FA.find(function(err, fas) {
if (err)
res.send(err);
res.json(fas);
});
});
//on routes that end in /FA/:FA_id
//----------------------------------------------------
router.route('/FA/:FA_id')
// get the bear with that id
.get(function(req, res) {
FA.findById(req.params.bear_id, function(err, fa) {
if (err)
res.send(err);
res.json(fa);
});
})
/*
* Athlete.
find().
where('sport').equals('Tennis').
where('age').gt(17).lt(50). //Additional where query
limit(5).
sort({ age: -1 }).
select('name age').
exec(callback);
*/
// update the bear with this id
.put(function(req, res) {
FA.findById(req.params.FA_id, function(err, fa) {
if (err)
res.send(fa);
//bear.name = req.body.name;
/*
FA.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'FA updated!' });
});
*/
});
});
/*
// delete the bear with this id
.delete(function(req, res) {
FA.remove({
_id: req.params.bear_id
}, function(err, FA) {
if (err)
res.send(err);
res.json({ message: 'Successfully deleted' });
});
});
*/
//*************************************************************************
//CREATE FP ROUTE
//*************************************************************************
router.route('/FP')
// create a FA (accessed at POST http://localhost:8080/DNZ/FP)
.post(function(req, res) {
//res.setHeader('Content-Type', 'application/json')
console.log("Erzeugen der Instanz FP..");
// create a new instance of the FP model
var fp = new FP(req.body);
//SAVE the new instance
fp.save(function(err) {
if (err) {
console.log(err);
res.status(400);
res.send(err);
}
else {
console.log("Instanz FP in Datenbank erzeugt!");
res.status(200);
res.json({ message: 'FP-Instance created in datbase!' });
}
});
})
// get all the FAs (accessed at GET http://localhost:8080/DNZ/FA)
.get(function(req, res) {
FP.find(function(err, fps) {
if (err) {
console.log(err);
res.status(400);
res.send(err);
}
else {
//res.send("Willkommen auf /FP");
res.json(fps);
}
});
});
//REGISTER OUR ROUTES -------------------------------and listen to requests
app.use('/DNZ', router);
//START THE SERVER
//=============================================================================
// set static directories
app.use(express.static('./dist'));
app.use(cors());
// Define Routes
var index = require('./routes/index');
var users = require('./routes/users');
//Set up routes
routes.init(app)
//run
app.listen(port);
console.log('Listen on port: ' + port);
console.log('Server started, Listening on port ', port);
This is primarily opinion based, but I had the same thing a while back and developed a way to extract route/model logic from the main file, using the module require-dir
In my app.js
/**
* Process ALL routes from routes dir utilising require-dir
*
* Allows us to include an entire directory, without replicating
* code, creating similar routes on a per end-point basis. This
* nicely keeps all end-point routes separate.
*/
var routes = requireDir('./routes');
for(var x in routes) {
application.use('/', routes[x]); // here, application is your express server instance
}
Then create a directory called routes and add whatever, for instance routes/branding.js:
var expressFramework = require('express');
var Branding = require('../models/branding');
var responseHelper = require('../shared/responseHelper');
var responseStatusCodes = require('../shared/responseStatusCodes');
var responseMessages = require('../shared/responseMessages');
var queryHelper = require('../shared/queryHelper');
var routerObject = expressFramework.Router();
var branding = new Branding();
var responsehelper = new responseHelper();
var queryhelper = new queryHelper();
/**
* Endpoint /branding/{chain_id}/{site_id}
*/
routerObject.get('/branding/:chain_id/:site_id', function(req, res, next) {
var requiredFields = [
{
chain_id: true, where: 'path'
},
{
site_id: true, where: 'path'
}
];
if (!queryhelper.authenticateToken(req.headers.authorization)) {
responsehelper.sendResponse(res, responseStatusCodes.STATUS_UNAUTHORISED,
responseMessages.RESPONSE_AUTHENTICATION_FAILED);
return;
}
if (!queryhelper.validateQuery(req, requiredFields)) {
responsehelper.sendResponse(res, responseStatusCodes.STATUS_INVALID_QUERY_PARAMS,
responseMessages.RESPONSE_INVALID_QUERY_PARAMS);
return;
}
branding.getBranding(req, function(err, results, pagination) {
if (err) return next(err);
if (results.length >= 1) {
responsehelper.sendResponse(res, responseStatusCodes.STATUS_OK, results);
} else {
responsehelper.sendResponse(res, responseStatusCodes.STATUS_NOT_FOUND,
responseMessages.RESPONSE_NO_RECORDS_FOUND);
}
});
});
module.exports = routerObject;
The key point here, is that you eventually export the express Router object, which your application, can 'use'. You'll also notice, that branding uses an include var Branding = require('../models/branding'); - This contains all the logic, whereas the route contains the end point definitions only, a snippet:
var Promise = require('bluebird');
var db = require('../shared/db');
var queryHelper = require('../shared/queryHelper');
var schemas = require('../schemas/schemas');
var _ = require('lodash');
var serverSettings = require('../shared/coreServerSettings');
// Create new instance of mysql module
var connection = new db();
var queryhelper = new queryHelper();
var queryAndWait = Promise.promisify(connection.query);
// Branding Object
var Branding = function(data) {
this.data = data;
};
Branding.prototype.data = {};
/**
* Branding methods
*/
Branding.prototype.getBranding = function(req, callback) {
var params = [];
var queryFoundRows = `select FOUND_ROWS() as total`;
var query = `select
id
from
company
where
1=1
and chain_id=?`;
params.push(req.params.chain_id);
queryAndWait(query + '; ' + queryFoundRows, params).then(function(result) {
return Promise.map(result[0], function(row) {
var params = [];
var query = `select
*
from
location
where
1=1
and company_id=?
and site_id=?`;
params.push(row.id);
params.push(req.params.site_id);
return queryAndWait(query, params).then(function(result) {
return result[0];
});
}).then(function(payload) {
callback(null, payload);
}).catch(function(err) {
callback(err, null, null);
});
});
};
module.exports = Branding;
May not be exactly what you're after, but should provide a good start point. Good luck!
This topic is subjective however - it is important to take a standard and stick to it. The way I handled this was by creating a subfolder with a module (using module.exports) and an init function that constructs the express app.
For every route I have another module that has an init function which accepts the express application as a parameter and then adds the routes in there.
Main code file:
var Api = require('./API/index.js');
File /API/Index.js:
var express = require('express');
/* Instantiations */
var app = express();
module.exports = {
...
apply();
...
}
var route1 = require('./Routes/route1.js');
var route2 = require('./Routes/route2.js');
/* all additional routes */
var Routes = [route1,route2,...]
function apply(){
for(var i=0;i<Routes.length;i++){
Routes[i].init(app);
}
}
Then in API/Routes/route1.js and API/Routes/route2.js...
module.exports = {
init: function(app){
/* add your route logic here */
}
}
The benefits of this approach in my experience is that you can optionally choose to add or remove routes as needed and it provides a readable route-path via the file system which is handy in most modern text editors.

NodeJS procedure execution flow

I am new to Nodejs and aslo coming from a procedural language background so I have this need to know the execution flow of my code. I have a general question about the flow of Nodejs procedures. This is the scenario:
The code structure:
Appnamefolder
...standard node folders(.idea,css,fonts,etc)
...model
....database.js (connect to db and execute db queries)
...public
...routes
....users.js (GET and POST procedures....calls db queries via module.export)
...views
...app.js
...other js files
The question concerns the database. Since the DB connect is not in the app.js file but in a .js file in the model folder at what point is the DB connection made? and is a connection made every time a DB query is made?
What I hope to happen is that the DB connect is made one time and remain connected until the app is terminated. I tried putting the DB connect in app.js but I get an error when I attempt a DB query so I have to place the DB connect in the same file as the DB queries......Somehow this seems wrong to me. Can anyone explain how node handle this flow?....will be appreciative of any assistance.
EDIT: HERE IS A SAMPLE OF THE CODE
app.js
var express = require('express');
var path=require('path');
var bodyParser = require('body-parser');
var cookieParser=require('cookie-parser');
var expressSession=require('express-session');
var expejs = require('ejs');
var expressValidator = require('express-validator');
var flash = require('connect-flash');
var expressSession = require('express-session');
var expressLayouts=require("express-ejs-layouts") // add this requirement
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var crypto = require("crypto");
var loaddealerTable=require('./loaddealerTable');
//var neo4j = require('neo4j-driver').v1;
// var neo4jdb = neo4j.driver("bolt://localhost:7474", neo4j.auth.basic("neo4j", "password"),
// {
// trust: "TRUST_ON_FIRST_USE",
// encrypted:true
// });
//***************Notifications Permission*******
var routes = require('./routes/index');
var users = require('./routes/users');
var csocket=require('./socketconnections');
var app=express();
var server=require('http').createServer(app);
sockets = require('./socketserver');
//rpaMessageWaiting = require('./getRPAmessages');
//var io=require('socket.io').listen(server);
// View Engine
app.set('views', path.join(__dirname,'views'));
app.set('view options', { layout:'layout.ejs' });
app.set('view engine','ejs');
//bodyParsers middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(expressLayouts);
//set up public folder
app.use(express.static(path.join(__dirname, '/public')));
// set express session with secret
app.use(expressSession({ secret: process.env.SESSION_SECRET || 'secret',
resave: true,
saveUninitialized: true
}));
// Passport initialization
app.use(passport.initialize());
app.use(passport.session());
//Express Validitor...validate inputs..taken from github middleware options
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
// connect flash middleware
app.use(flash());
// set global variables for flash messages
app.use(function (req, res, next)
{
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
res.locals.user = req.user || null;
next();
});
// Middelware for route files
app.use('/', routes);
app.use('/users', users); //need to check routing
sockets.startSocketServer(server);
//load dealer table
console.log("load dealer table");
**loaddealerTable(); //First call on the DB**
//============socket io listening=======================
app.set('port',(process.env.PORT|| 3000));
server.listen(app.get('port'), function()
{
console.log('Server started on port '+app.get('port'));
// console.log('Server started on port .....');
// app.get('/index',function (req,res) {
// // body...
// res.render(__dirname+'/index');
});
loaddealertable.js
var loaddealerTable=function()
{
var memorytbl=require('./memorytables');
var User = require('./model/user');
var getHashKey=require('./gethashkey');
const hashMax=1000;
console.log("call get dealers from DB");
User.getallDealers(function(err,dealerFound,result)
{
if (dealerFound)
{
//
for (i=0; i< result.records.length; i++)
{
memorytbl.Dealer.email =result.records[i].get(0).properties.email;
memorytbl.Dealer.name =result.records[i].get(0).properties.name;
memorytbl.Dealer.telephone =result.records[i].get(0).properties.storenumber;
memorytbl.Dealer.creditcard =result.records[i].get(0).properties.creditcard;
memorytbl.Dealer.delivery =result.records[i].get(0).properties.delivery;
memorytbl.Dealer.location =result.records[i].get(0).properties.location;
memorytbl.Dealer.rating =result.records[i].get(0).properties.rating;
var hashIndex = getHashKey(memorytbl.Dealer.email ,hashMax);
memorytbl.DealersQ[hashIndex]=memorytbl.Dealer;
} //end of for i
} //end of if....
else
{
console.log("No dealers found....table is empty");
}
}) //end of loaddealers table db call
} //end of load dealers table function
module.exports=loaddealerTable;
user.js
var express = require('express');
var bcrypt = require('bcryptjs');
var router = express.Router();
var neo4j = require('neo4j-driver').v1;
var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "password"));
var session = driver.session();
//============Load Memory Tables=========================
router.getallDealers=function(callback) {
session
.run ("MATCH (user:Dealer) RETURN user")
.then (function(result)
{
if ( !result.records[0])
{
console.log("No Dealers Found");
session.close();
if (typeof callback==="function") {
return callback(null,false,result);
}
} // end of if not found
else
{
console.log("Dealer Found");
session.close();
if (typeof callback === "function")
{
return callback(null, true, result);
}
}
// or close session here??
}) //end of .then block
.catch(function(err)
{
console.log("DB call error: "+err);
}); //.then block
} //end of get dealers
For a start you have to understand that each file is a module.
Your app starts with running a single js file (module) like node app.js.
One module can load another module and another and so on.
Your folder structure does not have any effect on the order by itself. It all depends on your code and in what order do you load modules. While your sync code will run in the order you write it your async code will run in the future and you need to understand the event loop to understand what happens in your code.
From the small context you gave I guess you might tried to query your database before you connected to it. I don't see your code but it can happen regardless of where you connect (app.js file or another).

Node.js Express Serve static files only with SIMPLE authentification

I've a problem since two days ago now.
I just want an authentification on my static files.
I look at a lot of post on the internet and nothing answer my question simply.
I try to use basic-auth, but it has no effect on my webpages.
I just want a simple dialog box before open my static pages that ask name and password and in my server.js just a thing like : if name == 'foo' and password =='pwd' then "send my static content".
But it seems to be not simple as it might be.
There is my code :
/***************************************************************************/
//Server Node.js
/** ************************************************************************ */
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
// Routers
var router = express.Router();
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost:27017/mydb');
var conn = mongoose.connection;
var assert = require("assert");
var basicAuth = require('basic-auth');
var auth = function (req, res, next) {
function unauthorized(res) {
res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return res.send(401);
};
var user = basicAuth(req);
if (!user || !user.name || !user.pass) {
return unauthorized(res);
};
if (user.name === 'foo' && user.pass === 'bar') {
return next();
} else {
return unauthorized(res);
};
};
app.use('/', auth);
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({"extended" : false}));
router.route("/data").get(function(req, res) {
// A non static route
});
}).post(function(req, res) {
// A non static route
});
router.route("/data/:id?").get(function(req, res) {
// A non static route
});
router.route("/remove/:id?").get(function(req, res) {
// A non static route
});
app.use('/', router);
app.listen(8080);
console.log("Listening to PORT 8080");
Thanks.
Have a nice day.

Passport + Socket.io get logged user id

I'm making a Node.js app and I need to create a new document in mongoDB inside socket.io.
I have to insert the logged in user in the new document.
How can I access the session variable inside socketio ?
// INCLUDE MODULES =======================================================
var SocketIOFileUpload = require("socketio-file-upload");
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var socketio = require('socket.io');
var Twig = require('twig');
var twig = Twig.twig;
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var Cookies = require( "cookies" );
var flash = require('connect-flash');
var configDB = require('./config/database.js');
var connect = require('connect');
var ImageFile = require('./app/models/image');
// Assets ================================================================
app.use(express.static(path.join(__dirname, 'public')));
app.use(connect.favicon(path.join(__dirname, 'public/images/favicon.ico')));
// Start mongoose
mongoose.connect(configDB.url);
// USER MANAGEMENT =======================================================
require('./config/passport')(passport); // pass passport for configuration
app.use(connect.logger('dev')); // log every request to the console
app.use(connect.cookieParser()); // read cookies (needed for auth)
app.use(connect.json()); // to support JSON-encoded bodies
app.use(SocketIOFileUpload.router); //socket io file upload
app.use(connect.urlencoded()); // to support URL-encoded bodies
app.set('view engine', 'twig'); // set up twig for templating
app.use(connect.session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash());
// Some more code ...
//SOCKET IO =======================================================
//Quand on client se connecte, on le note dans la console
var io = socketio.listen(server);
io.sockets.on("connection", function(socket){
// Make an instance of SocketIOFileUpload and listen on this socket:
var session = socket.handshake.session;
var uploader = new SocketIOFileUpload();
uploader.dir = "/LeafStore/public/uploads";
uploader.listen(socket);
console.log(socket.handshake.user);
// Do something when a file is saved:
uploader.on("saved", function(event, socket){
console.log(event.file);
});
// Do something when a file is saved:
uploader.on("complete", function(event){
console.log("saving file" + name);
console.log(event);
var name = event.file.name;
var imageData = {
name: name
, type: "image"
, userId: ""
, creationDate: new Date()
};
var newImage = new ImageFile(imageData);
newImage.save( function(error, data){
if(error){
throw error;
}
else{
}
});
// save the user
newImage.save(function(err) {
if (err)
throw err;
});;
});
// Error handler:
uploader.on("error", function(event){
console.log("Error from uploader", event);
});
});
// LISTEN SERVER =======================================================
server.listen(80);
I found a temporary solution :
I emit the user Id in my views :
socket.emit('userId', $("#userId").val());
Then I set the socket.userId var :
socket.on('userId', function(userId){
socket.userId = userId;
});
But it's probably unsafe

Node emitters with express

I want to make serial work on backend. I want to select geo_unit and do another work and write response to client.
I read http://nodejs.org/docs/v0.4.7/api/events.html#events and Error: Can't set headers after they are sent to the client
Everything works fine when I send the requests slowly e.g. 1 in each 3 seconds.
But it doesnot work when i send the requests fast. and i get the following error.
Do i define something globally?
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
at ServerResponse.res.setHeader (E:\git\xxxxxx-nodejs\node_modules\express\node_modules\connect\lib\patch.js:63:22)
at ServerResponse.res.set.res.header (E:\git\xxxxxx-nodejs\node_modules\express\lib\response.js:527:10)
at ServerResponse.res.json (E:\git\xxxxxx-nodejs\node_modules\express\lib\response.js:194:36)
at EventEmitter. (E:\git\xxxxxx-nodejs\routes\api_scrapper.js:17:17)
at EventEmitter.emit (events.js:117:20)
at ScrapperAPI.externalLocationCallback (E:\git\xxxxxx-nodejs\routes\api_scrapper.js:27:20)
at Query._callback (E:\git\xxxxxx-nodejs\routes\api_scrapper.js:51:21)
at Query.Sequence.end (E:\git\xxxxxx-nodejs\node_modules\mysql\lib\protocol\sequences\Sequence.js:78:24)
at Query._handleFinalResultPacket (E:\git\xxxxxx-nodejs\node_modules\mysql\lib\protocol\sequences\Query.js:143:8)
I am using the following code :
var express = require('express'),
http = require('http'),
path = require('path');
var app = module.exports = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var request = require('request');
var cheerio = require('cheerio');
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'localhost',
user : 'root',
database :'evevgez_development',
password : 'root',
// socketPath : '/var/run/mysqld/mysqld.sock'
});
var sahibinden = require('./routes/my_scrapper').newScrapperAPI(pool);
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
app.use(express.errorHandler());
app.get('/node1', sahibinden.scrap);
server.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
and myModule is like that
var request = require('request');
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
var EventEmitter = require('events').EventEmitter;
var emitter= new EventEmitter();
function ScrapperAPI(pool) {
this.scrap = function (req, res,next) {
var query = req.query;
console.log('req.params:'+req.query);
console.log('IL_ID:'+query.il_id);
emitter.emit('location',query);
emitter.on('success',function(rows){
res.json(rows);
});
};
emitter.on('location',function(query){
console.log('quey1:'+query);
getExternalLocation(query )
});
var getExternalLocation = function (query ) {
try {
pool.getConnection(function (err, connection) {
console.log('query:'+query);
connection.query("select * from external_geo_units where geo_unit_id = ? ",query.il_id, function (err, rows) {
console.log(err);
if (err) callback(err);
emitter.emit('success',rows);
connection.release();
});
});
} catch (e) {
console.log(e);
}
};
}
module.exports.newScrapperAPI = function (pool) {
return new ScrapperAPI(pool);
}
Using an EventEmitter in this way isn't the best solution for what you're doing, since you're just using it within a request to make a database call and return some rows -- something that could be more easily and simply done with just callbacks.
However if you want to keep the global EventEmitter, you have to switch the on in emitter.on('success' and emitter.on('location' to once instead, to ensure they only get called once per request.

Resources