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
Related
I really apologize if I'm leaving something out and am totally stupid, but I've checked and checked over again a number of times, and the file upload functionality is just not working over here. I made a super minimal app to demonstate. Just generated a new express app with the most up-to-date version (3.4.7) and added the least i could to make a file upload work.
Here's my app.js file
/**
* Module dependencies.
*/
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
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());
}
app.get('/tasks', function(req, res) {
res.render('form');
});
app.post('/tasks', function(req, res) {
console.log(req.files);
res.send('ok');
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
exports = module.exports = app;
And here's my form.jade view file:
doctype html
html
head
title Task Upload
body
form(action='/tasks', method='post', enctype='multipart/form-data')
input(name='task', type='file')
input(type='submit')
Everytime I try to upload a file, req.files logs out undefined. Can anyone save me out from this problem?
Add the following in your app.js
app.configure(function(){
app.use(express.methodOverride());
app.use(express.bodyParser({keepExtensions:true,uploadDir:path.join(__dirname,'/files'}));
});
And then try to access as follows;
req.files.task
It is recommended not to use bodyParser, but to simply define the type of handling you want. In your case since its file uploading, you can enable it as follows
app.configure(function(){
app.use(express.methodOverride());
app.use(express.multipart());
});
You can read about why using bodyParser() is not a good idea in the following link.
http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html
In Express 4, req.files is no longer available on the req object by default.
To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty,.
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 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?
I want to display a flash message after a user fails to sign in but I just can't get the variables to show up in my Jade views.
I have some pieces, I know I have to use this in my app.configure():
app.use (req, res, next) ->
res.locals.session = req.session
And I'll set what the flash message is after the user POSTS the wrong password:
exports.postSession = (req, res) ->
users = require '../DB/users'
users.authenticate(req.body.login, req.body.password, (user) ->
if(user)
req.session.user = user
res.redirect(req.body.redirect || '/')
else
req.session.flash = 'Authentication Failure!'
res.render('sessions/new', {title:'New', redirect: req.body.redirect })
)
I don't know how to access res.locals.session in my Jade file. I doubt I am setting everything up right. This question is a lot like this one: Migrating Express.js 2 to 3, specifically app.dynamicHelpers() to app.locals.use? but I still can't get it to work. It would be much appreciated if someone could show me just a simple example of setting values in res.local and accessing them in a view.
p.s. I do know about connect-flash but I need to understand how to make things available in views.
This is my app:
app.configure(() ->
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')
app.use(express.bodyParser())
app.engine('.jade', require('jade').__express)
app.use(express.methodOverride())
app.use(express.cookieParser())
app.use(express.session({ store: new express.session.MemoryStore({reapInterval: 50000 * 10}), secret: 'chubby bunny' }))
app.use(express.static(__dirname + '/public'))
app.use((req, res, next) ->
res.locals.session = req.session
next()
)
app.use(app.router)
)
Just to give a short summary for everyone who has the same problem and got the impression that is was solved changing res.redirect.
It is very important to put your app.use middleware before app.router. See the comments by TJ Holowaychuck, the author of express
https://groups.google.com/d/msg/express-js/72WPl2UKA2Q/dEndrRj6uhgJ
Here is an example using a fresh installation of express v3.0.0rc4
app.js:
app.use(function(req, res, next){
res.locals.variable = "some content";
next();
})
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());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
index.jade:
extends layout
block content
h1= title
p Welcome to #{title}
p= variable
If you are using express.session() you must call your function AFTER express.session() but BEFORE app.router, inside of app.configure().
app.js
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.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session());
// Give Views/Layouts direct access to session data.
app.use(function(req, res, next){
res.locals.session = req.session;
next();
});
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
index.jade
extends layout
block content
h1= title
p My req.session.var_name is set to #{session.var_name}
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.