So playing around with node, thought I would write a straight forward news ticker to put on my very minimalistic node page, seemed like fun. The thing is, I keep on getting
RangeError: Maximum call stack size exceeded
But I can not for the life of me figure out where the error occurs.
Have thrown is some additional debug comments, even removed parts of almost every file, but it all comes down to the same thing. If I start the application it gets to listening on port 3000 without problems. If I try to access it, i get the error message above.
Here is the app.js code
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, stylus = require('stylus')
, nib = require('nib')
, mongo = require('mongodb')
, logger = require('express-logger')
, bodyParser = require('body-parser')
, methodOverride = require('express-method-override')
, errorhandler = require('errorhandler')
, monk = require('monk');
var app = express();
//Is this specifically for nib and stylus to work
function compile(str, path) {
return stylus(str)
.set('filename', path)
.use(nib())
}
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
//app.use(express.favicon());
//app.use(express.logger('dev'));
//app.use(express.bodyParser());
//app.use(express.methodOverride());
app.use(app.router);
app.use(stylus.middleware(
{ src: __dirname + '/public'
, compile: compile
}
));
app.use(express.static(path.join(__dirname, 'public')));
//development only
//if ('development' === app.get('env')) {
//app.use(express.errorHandler());
//}
//Lets do some stuff to get info from the database
var db = monk('localhost:27017/meetallnews');
var router = express.Router();
//Make our db accessible to our router
app.use(function(req,res,next){
req.db = db;
next();
});
app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Also, the routes/index.js
console.log('Called index.routes');
var express = require('express');
var router = express.Router();
exports.index = function(req, res){
console.log('render page');
res.render('index', { title: 'Meet All' });
};
//This is to read from the database
router.get('/userlist', function(req, res) {
console.log('Called database');
var db = req.db;
var collection = db.get('sitenews');
collection.find({},{},function(e,docs){
res.render('newslist', {
"newslist" : docs
});
});
});
Any suggestions welcome, even where to start looking. I removed the whole route.get section above, and still got the same (or an identical) error. Tried to remove stuff from the jade file, to the extent where there was only the header line left, still the same error message. And always after the server have reached end of app.js (have said Server on port 3000)
Thank you very much lukaszfiszer and Mr Pomax.
Turns out that the error message was a bit misleading, making me think it was some kind of eternal loop or some strange stuff from the database.
It was because I am a horrible thief and stole some code from somewhere for the routes, and missing to remove the line app.use(app.router); when also having routes = require('./routes')
Once that was removed I got a brand new error that I understand where it comes from and what it is (and not really related to this issue, only proves that untested coded must be tested.
Related
I'm learning MEAN stack with 'Getting MEAN with...' book, and problem is older Express version in books than i use.
The first step is to tell our application that we’re adding more routes to look out for,
and when it should use them. We already have a line in app.js to require the server
application routes, which we can simply duplicate and set the path to the API routes
as follows:
var routes = require('./app_server/routes/index');
var routesApi = require('./app_api/routes/index');
Next we need to tell the application when to use the routes. We currently have the following line in app.js telling the application to check the server application routes for
all incoming requests:
app.use('/', routes);
Notice the '/' as the first parameter. This enables us to specify a subset of URL s for
which the routes will apply. For example, we’ll define all of our API routes starting
with /api/ . By adding the line shown in the following code snippet we can tell the application to use the API routes only when the route starts with /api :
app.use('/', routes);
app.use('/api', routesApi);
And there's listing of my app.js file:
var express = require('express')
, others = require('./app_server/routes/others')
, locations = require('./app_server/routes/locations')
, routesApi = require('/app_api/routes/index')
, ;
require('./app_server/models/db')
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/app_server/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
// LOCATION PAGES
app.get('/', locations.homeList);
app.get('/location', locations.locInfo);
app.get('/location/review/new', locations.addReview);
// OTHER PAGES
app.get('/about', others.about);
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
Can someone explain me how to do the same in my Express version ?
In Express 4, this is done using Router Middleware. More info is available on Express Routing here.
A Router is simply a mini express app that you can define middleware and routes on that should all be packaged together, ie /api should all use apiRouter. Here is what apiRouter could look like
apiRouter.js
var express = require('express')
var router = express.Router(); // Create our Router Middleware
// GET / route
router.get('/', function(req, res) {
return res.status(200).send('GET /api received!');
});
// export our router middleware
module.exports = router;
Your main Express app would stay the same, so you would add your router using a require() to import the actual file, and then inject the router with use()
Express Server File
var express = require('express');
var app = express();
var apiRouter = require('../apiRouter');
var port = process.env.PORT || 3000;
app.use('/', apiRouter);
app.listen(port, function() {
console.log('listening on ' + port);
});
When running express, the generated app.js is the following: (at the date of this post)
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use(function(req, res, next) {
...
});
if (app.get('env') === 'development') {
...
}
app.use(function(err, req, res, next) {
...
});
module.exports = app;
For simplicity I removed comments.
My question is really simple:
I've seen a lot nodeJS examples in websites, blogs, and docs, where they use one of the followings:
require('http').createServer(app).listen(3000);
or
app.listen(3000);
If I execute my generated express app (npm start), it runs. I can navigate to localhost:3000 with a browser and it is being served. So... how relevant is to use listen(port)?
Im asking this because I like to have full control of things.
Also, some examples of modules use listen, eg. module Sequelize
Article: "Usage with Express.JS",
link: http://sequelizejs.com/articles/express,
app.js
------
db
.sequelize
.sync({ force: true })
.complete(function(err) {
if (err) {
throw err[0]
} else {
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'))
})
}
})
This makes me think that I should sync before starting listening.
If I dont use listen, and let it listen automagically (as the generated code does), will I get troubles because of syncing and listening at the same time?
If you look at the package.json file you'll probably find its running /bin/www or some such startup script. That will have the "missing" listen statement.
I have a node.js server with express Framework.
var express = require('express');
var http = require('http');
var api_helper = require('./helpers/api_helper');
var app = express();
app.use(app.router);
app.use(express.bodyParser());
app.set('port', process.env.PORT || 8081);
app.post('/api/nodev1/users/login', function(req, res){
var email = req.param('email', null);
var password = req.param('password', null);
console.log(email);console.log(password);
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
When I try to post a request to /api/nodev1/users/login I cannot read the parameters. I am trying with curl as follows:
curl -d "email=user#example2.com" -d "password=mypassword" http://localhost:8081/api/nodev1/users/login
The email and password are undefined.
You have to move app.use(app.router) below app.use(express.bodyParser()). app.router is just a hook in which stage to handle your routes. And if it comes before bodyParser the body is not parsed.
Your code could look like this (in case I didn't manage to explain understandable):
var app = express();
app.use(express.bodyParser());
app.set('port', process.env.PORT || 8081);
app.use(app.router);
// I added following line so you can better see what happens
app.use(express.logger('dev'));
app.post('/api/nodev1/users/login', function(req, res){ ... }
Offtopic remark: express.bodyParser() should only be used when you have file-uploads. And then you have to take care of deleting temp-files. If you don't have file-uploads, you are better off with only
app.use(express.json());
app.use(express.urlencoded());
I just wanted to add this in case you didn't know. I ran in problems because I didn't know...
Edit for Express 4
Thanks to #jonathan-ong there is no app.use(app.router) since Express 4:
All routing methods will be added in the order in which they appear. You should not do app.use(app.router). This eliminates the most common issue with Express.
In other words, mixing app.use() and app[VERB]() will work exactly in the order in which they are called.
Read more: New features in 4.x.
edit - nope, see other answer about middleware order!
change req.param to req.body.x:
app.post('/api/nodev1/users/login', function(req, res){
var email = req.param('email', null);
var password = req.param('password', null);
console.log(email);console.log(password);
});
to
app.post('/api/nodev1/users/login', function(req, res){
var email = req.body.email);
var password = req.body.password);
console.log(email); console.log(password);
});
i am trying to create a route for localhost:port/admin/
and i want to keep the routes.js files and view.js files in matching folders so i wont have too much spaggeti later on
but i keep getting: 500 Error: Failed to lookup view "/admin/manage_subjects"
for trying to create a new route and using same folders few the same
i have the following view folder with express
mainapp(root)
routes(folder)
admin(folder)
index.js(nested inside admin)
index.js(nested inside routes)
views(folder)
admin(folder)
admin_layout.jade(nested inside admin)
manage_subjects.jade(nested inside admin)
index.jade(nested inside views)
layout.jade(nested inside views)
code:
routes/admin/index.js
exports.index = function (req, res) {
res.render('manage_subjects',{title:'Express'});}
views/admin/manage_subjects.jade
extends admin_layout
block content
h1 = title
p Welcome to #{title}
my app.js code
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, admin_routes = require('./routes/admin/')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, repository = new (require('./domain_model/repository'))();
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//fill local subjects
repository.subjects.GetAll(function (err, data) {
if (err) throw err;
app.locals.subjects = data;
});
//append routes
app.get('/', routes.index);
app.get('/admin', admin_routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on http://localhost:' + app.get('port'));
});
I've been dealing with what I think is the same problem and figured out how to fix it. So in case someone else comes across this problem I'm posting my solution.
So here is what I had that was causing 404's and 500's
app.js
var routes = require('./routes/index');
var admin = require('./routes/admin');
app.use('/', routes);
app.use('/admin', admin);
and here was my routes/index.js
//append routes
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});
module.exports = router;
and my routes/admin.js:
var express = require('express');
var router = express.Router();
router.get('/admin', function(req, res) {
res.render('admin/index', {title: 'Express'});
});
module.exports = router;
by defining the second /admin inside the router.get() function I think I was effectively telling node to look for the html in my views folder under the following path views/admin/admin/index.ejs. So to fix that all I had to do was remove either the /admin from the router.get() or the /admin from the app.use()
So my working code now looks like this:
app.js
var routes = require('./routes/index');
var admin = require('./routes/admin');
app.use('/', routes);
app.use('/admin', admin); //I left the /admin here and instead removed the one in routes/admin.js
and here was my routes/index.js
//append routes
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});
module.exports = router;
and my routes/admin.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) { //NOTICE THE CHANGE HERE
res.render('admin/index', {title: 'Express'});
});
module.exports = router;
So making that change made it so I could have sub folders in my views folder.
Simple Answer for sub-folders inside the views folder (mine is called frontend)
click here the picture to see the folder structure
file app.js
app.set('views', [path.join(__dirname, 'frontend'), path.join(__dirname, 'frontend/locked'), path.join(__dirname, 'frontend/template'), path.join(__dirname, 'frontend/public')]);
app.set('view engine', 'pug')
I'd check out TJ's video on Modular apps on his vimeo the best part about this work flow is your code becomes really flexible and it's alot easier to stay DRY.
Additionally I would do something like this with my app.set("views")
var path = require("path");
app.set('views', path.join(__dirname, 'views'));
// you can then extend this to the example for routes
Another alternative would be something like in your app.js file:
var express require("express")
var app = express()
var routes = require("./path/to/routes")(app)
and then routes would look like:
routes = function (app) {
app.get("/route", middleWareifYou.gotIt, route.handler || function (req, res) {
res.send("some msg");
});
};
module.exports = routes
Cheers, I hope this helps!
I had a similar problem and what worked for me was setting the views folder in both the main app file and in the router file too.
So in the main app.js file I had:
app.set('views', viewsFolderPath);
And inside my router.js file I also did the same thing:
app.set('views', viewsFolderPath);
I have done this before... I don't follow what I'm doing wrong this time, but I've been struggling for a couple of hours and now consider myself mentally blocked. The corresponding code:
app.use(express.bodyParser());
app.use(i18next.handle);
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view engine', 'swig');
app.set('view cache', false);
var session_store = new RedisStore({ client : redis_client});
app.use(express.errorHandler({ dumpExceptions : true, showStack : true}));
app.use(express.cookieParser());
app.use(express.session({ store : session_store, secret : SESSION_SECRET, key : "sid" }));
app.use(app.router);
Then when handling requests, here's just an example:
app.get('/session_test', function (req, res, next) {
console.log(req.session); //undefined
});
Connection to redis is working just fine. No errors are shown. Then, when trying to access it from the request, the req.session is undefined. The browser is sending the correct sid.
I'm no expert on the exact flow that occurs during the request, but after debugging, it seems as if the router was being called before the session middleware.
Thanks in advance for any and all the likely help. I will provide any code I can, I'm unsure what might be of your help.
Here's more code.
server.js
//Dependency modules
var express = require('express'),
app = express.createServer(),
//Application dependency modules
settings = require('./settings'), //app settings
routes = require('./routes'), //http routes
rtroutes = require('./rtroutes'); //real time communication routes (io)
var io = require('socket.io').listen(app);
var appWithSettings = settings.setup(io, app);
routes.settings.setup(appWithSettings);
rtroutes.settings.setup(io, appWithSettings);
No routes are added until routes.settings.setup is called. settings (which is the global settings) is a pretty big file. That's where all configuration is done. Settings are not added until settings.setup method is called too. Here's a cut of the file:
//Dependency modules
var express = require('express'),
redis = require('redis'),
//Important configuration values
var SESSION_SECRET = 'some secret thing which doesnt belong to stackoverflow!',
insert_other_variables_here = "lalala";
//Computed general objects
var RedisStore = require('connect-redis')(express),
redis_client = redis.createClient(REDIS_PORT, REDIS_HOST);
exports.setup = function (io, app) {
app.configure(function () {
app.use(express.bodyParser());
app.use(i18next.handle);
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view engine', 'swig');
app.set('view cache', false);
var session_store = new RedisStore({ client : redis_client});
app.use(express.errorHandler({ dumpExceptions : true, showStack : true}));
app.use(express.cookieParser());
console.log("ABOUT TO ADD SESSION STORE MIDDLEWARE");
app.use(express.session({ store : session_store, secret : SESSION_SECRET, key : "sid" }));
console.log("AND NOW ADDED THE SESSION STORE MIDDLEWARE");
app.use(app.router);
});
app.configure('development', function () {
//some things in here, but nothing that affects app. I have commented this
//for debugging and it changed nothing
});
app.configure('production', function () {
//mostly configuration for io and some caching layers, as well as servers info
app.use(express.errorHandler());
app.use(express.logger({ stream : logFile }));
});
app.listen(WEB_PORT);
return {
app : app,
//some other stuff that isn't relevant
}
}
I have 25 routes split in 4 different files (somehow I didn't have a need for session until now, since I was delaying some parts and everything needed was done with Mongoose). Here's an example of how it is being done (with fake names):
routes/index.js
export.settings = require("./settings");
routes/settings.js
exports.setup = function (app_settings) {
require("./route1")(app_settings);
require("./route2")(app_settings);
require("./route3")(app_settings);
};
Here's a stripped out "route1" file ("routes/route1.js"):
module.exports = function (app_settings) {
var app = app_settings.app;
console.log("ABOUT TO ADD ROUTES")
app.get("/signin", function (req, res, next) {
console.log(req.session); //this will be undefined
});
app.get("/register", function (req, res, next) {
});
app.get('/language', function (req, res, next) {
});
app.post('/settings', function (req, res, next) {
});
console.log("ADDED ROUTES NOW!")
}
Whenever you define a route, the router gets automatically inserted into whatever the middleware stack is at the time (subsequent attempts to insert it deliberately will be ignored). Are you sure you aren't defining any routes before you set the session handler?
Forgot to update this: Ebohlman set me in the right track.
It was i18next. When calling one of the init method it sets up routes and it was forcing app.router to be forced into the handle stack sooner. My bad, I didn't realize that part of the code was interacting with the app object and it did.
There was no way the question could have been answered better than how he did with the information I gave, so I am marking his answer as right.
I should try sleeping more v.v