Node Express Routing Problems - javascript

I´m currently trying to render my .ejs-templates with some variables, but I´m kinda stuck and can`t help myself. I´ve installed express over the express-generator with compass and ejs.
In my routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.write('Hello World')
res.end();
});
module.exports = router;
So I want to render <%= name %> in index.ejs (views/index.ejs) with the name Jack. In a few tutorials it should work this way, but it just don`t works for me.
I got an error telling me that the variable name is not defined. Would be very nice, if you guys could tell me, what I´m doing wrong or what I´ve missed.
I´m using ejs the first time and just can`t figure out my mistake =/
This is my app.js server-file
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var http = require("http");
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('node-compass')({mode: 'expanded'}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
regards,
Cab
edit: I figured out that the rendering of the variable title works, but all the other variables don`t work. I can imagine, that I can only access some kind of global variables and title is one of them =/
edit2: Found out, that my routing isnt working properly ... so the rendering isnt working ofc. But can`t figure out my mistake =/

If you have split your project up into different modules then you need to export those modules so they are available in other parts of your app.
For example you have separate route modules where you are defining your routes. For these to be available to the rest of your app then you need to make them available using the module.exports command.
so at the end of routes/index.js you need to have
module.exports = router;
The end of the express page on routing gives an example

Related

Express node.js - understanding routing

I have this about.js route and it works fine but I don't understand how / in router.get() would work while /about wouldn't?
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('about', { title: 'About' });
});
module.exports = router;
----------------- UPDATE ----------------------
It's basically what I got out of the box after installing express.js
except the about lines.
I expected router.get('/about' ...) in about.js would work but it threw an error and it worked with / instead and that's what bugs me.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-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 about = require('./routes/about');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/about', about);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
The problem
When you define a route on your app.js as you did with app.use('/about', about);. You are already telling express that you expect requests to hit http://yourserver/about route.
If you try to define /about again inside your about.js with:
router.get('/', function(req, res, next) {
res.render('about', { title: 'About' });
});
What you're doing is tellig the Express that you will hit a /about inside your firstly declared /about. So it will expect requests on this route: http://yourserver/about/about
The solution
It's actually what you're using. Define a root route inside your about.js as:
router.get('/', function(req, res, next) {
res.render('about', { title: 'About' });
});
This way your app will be:
Modular since you're using different files for different routes (about.js, users.js)
Easier to read
With simplier routes inside each file, since you don't need to type /about everytime you wish to create a new route.
If you wish a http://yourserver/about/help simply add a handler inside your route file about.js as here:
router.get('/help', function(req, res, next) {
res.render('help', { title: 'Help' });
});
If you want the route /about work then you have to create another route:
router.get('/about', function(req, res, next) {
res.render('about-page', { title: 'About' });
});
because / will only work for the home page.

Basic nodejs route resulting in 404

I am trying to create two separate routes in NodeJS, I am using the express framework and angular on the client side. I am currently able to render my index page successfully by visiting localhost:3000/ although when I try to render the login page by visiting localhost:3000/login I am getting a GET /login 404 error and not sure why b/c I set it up extremely similar to the index route. Not sure if I missed something.
This my app.js
//require dependencies
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//require routes but do not user yet
var routes = require('./routes/index');
var login = require('./routes/login');
//start app
var app = express();
// view engine setup - default views directory
app.set('views', path.join(__dirname, 'views'));
app.locals.delimiters = '<% %>';
app.set('view engine', 'hjs'); //use hogan templating for views
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/login', login);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
routes/login.js
var express = require('express');
var router = express.Router();
router.get('/login', function(req, res){
res.render('login');
});
module.exports = router;
views/login.hjs
<!DOCTYPE html>
<html>
<head>
</head>
<body>
HELLO WORLD
</body>
</html>
Visiting localhost:3000/login renders the following:
{{ message }}
{{ error.status }}
{{ error.stack }}
When writing app.use('/login', login), you are telling Express to use your router under the namespace : '/login'; Therefore, all routes defined into login.js don't need this prefix.
Try to access localhost:3000/login/login ;)
Then, just change your router to:
router.get('/', function(req, res){
res.render('login');
});

How to set the build environment using Node.js and AngularJS?

I've created a build environment using express JS. But, I got into trouble to configure AngularJS view -- Pleas help me to fix this issue..
1:
var express = require('express');
var http = require('http');
var path = require('path');
var favicon = require('serve-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();
var httpServer = http.createServer(app);
// view engine setup
//app.set('views', path.join(__dirname, 'views'));
//app.set('view engine', 'jade');
//res.render('dist/index.html');
//app.engine('html', require('ejs').renderFile);
//Trying to setup my view over here -- dist folder is holding the index.html file
app.set('views', __dirname + '/dist');
app.set('view engine', 'html');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/dist/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static('./dist'));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
httpServer.listen('8080');
console.log("server is started");
Above build setup was throwing following error ::
Error : Can't find module 'html' -- I'm not sure how to configure Node.Js to refer the angular JS veiw and all the injuctors..
The problem is with this line:
app.set('view engine', 'html');
You are trying to specify view engine with html value, which is not a view engine (expressjs tries to require html module internaly, but doesn't find it). If you need to serve just html files without templating use:
app.use(express.static(__dirname + '/public'));
And move all files you want to serve to public folder.
UPD: you can actually require html file from jade
in views/index.jade
include plain.html
in views/plain.html
<!DOCTYPE html>
...
and app.js can still just render jade:
res.render(index)
Andrew Homeyer's answer
References:
http://expressjs.com/4x/api.html#app.engine
How do I use HTML as the view engine in Express?
http://expressjs.com/guide/using-template-engines.html

Why the /users route in Express and Node?

Edit: The default express app is this:
var express = require('express');
var path = require('path');
var favicon = require('serve-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');
----------------------------------------
These refer to files that look like:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
module.exports = router;
------------------------------
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
However, the documentation says:
// this middleware will not allow the request to go beyond it
app.use(function(req, res, next) {
res.send('Hello World');
})
// requests will never reach this route
app.get('/', function (req, res) {
res.send('Welcome');
})
So my question, is why would a request ever make its way to the /users route when a default (i.e. '/') route has already been specified? Is it because routes and users are not functions?
On a related note, why even specify the / if that is what is used by default each time?
Lastly, the default app specifies the '/users' route: Why not just put another path in the index.js route? I am confused how the app can specify app.use('/users', users) and then, in the users route, specify
router.get('/', function(req, res) {
res.send('respond with a resource');
});
What does the / correspond to? It seemed like all requests to / would be handled by the first route (the one that use the routes default file)
app.use() is middleware. You pass it an optional path and a function and it is the function's job to decide if it wants to pass the request on to further middleware or further routes. It does that by calling next() or if it doesn't want to pass it on, it doesn't call next().
So, if you have:
app.use("/", fn);
That middleware will get called for all paths, but the code inside the function you pass it decides whether to pass the request on or not.
There are two routers in the Express 4 application skeleton: routes (mounted on '/') and users (mounted on '/users'). You may use both of them or only routes or you may even add more routers.
app.js:
var routes = require('./routes/index');
var users = require('./routes/users');
app.use('/users', users); // please note the mounting point!
app.use('/', routes);
users.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
Please note that router.get('/', ... ) for the users router means that the requested url is http://yourserver/users and not http://yourserver/

file upload in express js giving problems again

Though I have read quite a few questions being answered on stackoverflow, I'm still unable to get it to work even after a couple of days of trying. It's my first week with express and node and so I don't know if I'm doing the small things right. I basically want to upload a file and later on save it to the file system, however, I'm unable to proceed with req.files giving me undefined. Please see my code below.
This is my app.js
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var routes = require('./routes/index');
var users = require('./routes/users');
var upload = require('./routes/upload.js');
var app = express();
// view engine setup
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('/upload', upload);
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
This is my routes/upload.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
console.log("");
console.log(req.files);
res.send('this is the page you get upon doing file upload');
});
module.exports = router;
This is my views/homepage.jade
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
p select file to upload
form(action="upload", method="get", enctype="multipart/form-data")
input(type="file", name="displayImage")
input(type="submit")
At the moment, I'm hearing a lot of terms like multer, connect-busboy, bodyParser being deprecated from express4 etc but with no real idea on how to proceed. Please advise me on how I can proceed and what code should be added.
Thanks.
You need a middleware module that can parse your uploaded file.
Like such:
https://github.com/expressjs/multer
https://github.com/mscdex/connect-busboy
Then use the middleware in your index.js, like:
app.use(multer({ dest: './uploads/'}))
or
app.use(busboy());
A number of modules were removed from Express in 4.0 and are now separate packages you have to include. The easiest way to get started with it is to use express-generator to generate the scaffolding for you. This will include and require the correct packages for parsing cookies, and the request body. It doesn't include a file parser however. I put together an example using multer and put it on Github for you to reference.
After you clone it, you can run npm install, and then npm start.
One other thing you were doing incorrectly that I fixed was using app.get for your upload handler. You can't use GET to upload a file. In my example I changed this to a POST request. Here are the relevant snippets.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var multer = require('multer');
var routes = require('./routes/index');
var users = require('./routes/users');
var upload = require('./routes/upload');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(multer({ dest: './uploads/'}))
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/upload', upload);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
index.jade
extends layout
block content
h1= title
p select file to upload
form(action='upload', method='post', enctype='multipart/form-data')
input(type='file', name='displayImage')
input(type='submit')

Categories

Resources