I am playing with node and was trying to set a cookie on a request but am getting an undefined exception. Here is my sample application
var express = require('express');
var app = module.exports = express();
process.env.NODE_ENV = 'production';
app.configure('production', function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.get("/", function(req, res){
res.cookie('cart', 'test', {maxAge: 900000, httpOnly: true});
res.send("OK");
});
app.get('/users/:id', function(req, res) {
var s = req.params.id;
res.send('testcookie: ' + req.cookies.cart);
});
app.listen(3000);
console.log('Listening on port 3000');
I can validate in Charles that I am getting and returning the cookies:
But the result whenever I go to /users:id (where :id is obviously some number) I get a message saying the cookies object is undefined.
TypeError: Cannot read property 'cart' of undefined
at c:\Projects\app\app.js:29:42
at callbacks (c:\Projects\app\node_modules\express\lib\router\index.js:161:37)
at param (c:\Projects\app\node_modules\express\lib\router\index.js:135:11)
at param (c:\Projects\app\node_modules\express\lib\router\index.js:132:11)
at pass (c:\Projects\app\node_modules\express\lib\router\index.js:142:5)
at Router._dispatch (c:\Projects\app\node_modules\express\lib\router\index.js:170:5)
at Object.router (c:\Projects\app\node_modules\express\lib\router\index.js:33:10)
at next (c:\Projects\app\node_modules\express\node_modules\connect\lib\proto.js:199:15)
at Object.expressInit [as handle] (c:\Projects\app\node_modules\express\lib\middleware.js:31:5)
at next (c:\Projects\app\node_modules\express\node_modules\connect\lib\proto.js:199:15)
I've read all the other SO questions about putting the cookieParser above the other middleware, and from all accounts this example SHOULD work, but I'm at a loss as to what is missing.
Ok, turns out that it has to do with how I set up app.configure. The configure callback function wasn't getting called because the internals of app configure weren't calling the initialization function for the production ENV even though I thought it was explicitly set above.
To fix that, I changed the process.env.NODE_ENV to app.settings.env and everything started to work.
Found that info here: how to find out the current NODE_ENV the express app is running under?
Related
I'm tinkering with server side requirejs and I have a problem with routes. My routes/index.js file has:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
});
and in my server.js I have:
define(['express', 'module', 'path', './routes'],
function (express, module, path, routes) {
var app = express();
app.configure(function() {
// all environments
var filename = module.uri;
app.set('port', process.env.PORT || 3000);
app.use(express.static(path.dirname(filename) + '/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(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.dirname(filename) + '/public'));
});
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
return app;
});
When I run this I get the following error:
500 Error: Failed to lookup view "index"
at Function.app.render (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/application.js:489:17)
at ServerResponse.res.render (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/response.js:755:7)
at exports.index (/Users/johnwesonga/backbonejs/src/helloworld/routes/index.js:7:9)
at callbacks (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/router/index.js:161:37)
at param (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/router/index.js:135:11)
at pass (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/router/index.js:170:5)
at Object.router (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/lib/router/index.js:33:10)
at next (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at next (/Users/johnwesonga/backbonejs/src/helloworld/node_modules/express/node_modules/connect/lib/middleware/session.js:313:9)
Any clue where i'm going wrong?
It could be simply that something has been cached or needs to be restarted.
Unfortunately I don't have a definitive answer, but I was having a similar problem: everything seemed to be set up correctly however I was getting an error saying that it couldn't find the view. I gave up, switched off the computer then came back to it the next morning.....and it worked.
I hope this provides a clue for anyone looking at this post, (as I did), in the future
Hi i am following peepcode nodejs screencast, now i have an issues of rendering the login form. My code are as follow:
app.js
/**
* Module dependencies.
*/
require('coffee-script');
var express = require('express')
, http = require('http')
, path = require('path');
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());
}
require('./apps/authentication/routes');
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
and my i have a routes within authentication folder. The code as follow:
routes.coffee
routes = (app) ->
app.get '/login', (req,res) ->
res.render "views/login",
title: 'Login'
stylesheet: 'login'
module.exports = routes
The coffee script indentation all works fine, but i have an error when i navigate localhost:3000/login on browser. The error it display are Cannot GET /login. Where am i wrong?
In app.js, change this line:
require('./apps/authentication/routes');
to this:
require('./apps/authentication/routes')(app);
What is happening is that in routes.coffee, you're exporting a function that takes a single arg, 'app', and then sets up the route on your app object. You need to call it passing app as the argument.
I am using latest version of express no.3 . I have read the docs and did exactly as was written but it is still not working as it suppose to .I get file in my upload dir after submit but then everything stops and callback function from app.post doesn't fire . The code:
HTML-JADE
form(action="/upload", method="post", enctype="multipart/form-data")
input(type="file", name="image")
input(type='submit', value='submit')
App.js
var express = require('express')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, mongo = require('mongodb')
, Server = mongo.Server
, Db = mongo.Db
, routes = require('./routes')
var app = express();
app.configure(function(){
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({uploadDir:'./upload'}));
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
});
app.post('/upload', function(req, res) {
console.log(req.files.image) // this doesn't fire at all - no matter what i write here
res.send(200) //doesn't run also
});
You need to return a response after reading the data. Without returning a response, express has no idea of when your response is finished and node will not close the connection to the client.
try this:
app.post('/upload', function(req, res) {
console.log(req.files.image);
req.on('data', function(raw) {
console.log('received data');
});
req.on('end', function() {
console.log('end');
res.send(200);
});
}
Try sending a simple response to the user.
app.post('/upload', function(req, res) {
console.log(req.files.image);
res.write('File Uploaded !!');
res.end();
}
Update
You should try changing the format to
app.post('/upload', function(err,req,res,next){
//Check for errors then handle it
}
Can't tell much until I know what errors you are getting, since file is being uploaded to upload dir bodyParser is working fine. Maybe your route is being handled by another function, or not handled at all. app.router is code that calls the callback .
When you do app.get('/upload', function(req, res) { ... }); it is the router that actually invokes the callback function to process the request. Can you confirm if you can do app.get('/upload',...); the html-jade file succesfully. If not then there is a problem in your routes.
Finally I found solution - that was because i used node 0.9.6 -pre. After change to 0.8.21 everything works fine.
Thanks all for your help.
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
I don't seem to get JSHTML to work as a template engine on Express.js in Node.js. When I install my Express.js application and a basic application is created for me, and I run it I get this error message:
500 TypeError: Property 'engine' of object #<View> is not a function
at View.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/response.js:677:7)
at exports.index (/Users/blackbook/nodejs/ds/routes/index.js:7:7)
at callbacks (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:165:11)
at param (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:139:11)
at pass (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:146:5)
at Router._dispatch (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:173:5)
at Object.router (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:33:10)
at next (/Users/blackbook/nodejs/ds/node_modules/express/node_modules/connect/lib/proto.js:190:15)
My app.js looks like this (it's what Express.js created for me):
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
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')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
I have this installation:
Node.js v.0.8.5
Express.js#3.0.0rc2
jshtml#0.2.3
JSHTML currently works with Express.js 2. There are plans on getting the engine to work with Express.js 3, but currently I am too busy with enjoying the summer! Expect a fix for this problem in the winter!
According to https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x you can use app.engine for 2-x compatibility.
e.g.
var fs = require("fs");
var jshtml = require("jshtml");
app.engine("jshtml", function (path, options, fn) {
fs.readFile(path, 'utf8', function (err, str) {
if (err) return fn(err);
str = jshtml.compile(str,options)(options).toString();
fn(null, str);
});
});
consolidate.js is used as a bridge between many template engines and express. If your engine isn't supported checkout the source code. Most engines need like 15 lines of code to implement.
I have it working in my project and will probably issue a pull request soon but for now look at my comment in
https://github.com/elmerbulthuis/jshtml/issues/5
Try the following. It works for me, as like you.
Firstly, install jshtml-express via npm and then do the following.
var app = express();
**app.engine('jshtml', require('jshtml-express'));**
// All environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
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')));
I hope it will work for you as well.