I have a 2 routes, the first for an API and the second is a catch all which shows an html page. Now, even if I make a request to .../api/... via a browser, and see the "Invalid" - the second route, ie "called unnecessarily" still gets executed. I'm confused as to why the second route is called since it's already gone via the first route.
// api route
app.get("/api/appname/stuff_settings/:setting", function(req, res) {
// do api stuff
res.send(500, 'Invalid');
});
app.engine('.html', require('ejs').__express);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
// catch all route
app.use(express.static(path.join(__dirname, 'public')));
app.get('*', function(req, res){
res.render('index', {
console.log("called unnecessarily");
});
});
Do console.log(req.url); in the catch all route my money is on favicon.ico.
Related
If I path to a view in ./views express will render it but it doesn't that for example ./views/api/login.jade and it send 500: Internal Server Error.
my codes:
/* GET api/... */
router.get('/login', function(req, res, next) {
res.render('api/login.jade', { title: 'Login' });
});
Thanks
You have to set the views path as well.
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
router.get('/login', function(req, res, next) {
res.render('api/login', { title: 'Login' });
});
step 1: you have to make sure you are using jade as the view engine.
app.set('view engine', 'jade');
step 2: set view path
app.set('views', __dirname);
or you can write it in every render call, res.render(__dirname+'api/login')
Step 3: do not write extension names
router.get('/login', function(req, res, next) {
res.render('api/login', { title: 'Login' });
});
P.S.
i recommend that you start using pug instead of jade since pug is jade 2.0
I'm trying to set some response-specific variables, and I'm getting undefined for res.locals when I log it from within my middleware, but it returns the function just fine if I log it from within a route function.
// 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(function (res, req, next) {
console.log("res.locals from app.use middleware: ", res.locals);
// res.locals.boom = 'nice';
// res.locals.zoom = 'yeah!';
next();
});
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
Any ideas?
You have your request & response objects backwards. Obviously if you know the difference in your code, naming doesn't matter, but best to keep things named correctly.
app.use( function (request, response, next) {
// stuff
});
I can't recall off the top of my head, but I believe you want:
request.app.locals;
using my example above. Again, not 100% sure. You can always console out the request object to check.
The app.locals object is a JavaScript Function, which when invoked with an object will merge properties into itself, providing a simple way to expose existing objects as local variables.
app.locals({
title: 'My App',
phone: '1-250-858-9990',
email: 'me#myapp.com'
});
app.locals.title
// => 'My App'
app.locals.email
// => 'me#myapp.com'
Struck with routing issue in expressjs and AngularJs project.
It's not a single page application and I am not using any view engines such as jade.
We are just using plain HTML.
I am working on password reset functionality where user can reset the password by clicking a link provided by an email. So I assume there won't be any route change event in the context of Angular (Please correct me if I am wrong).
And my express configurations are as follows.
routes = require('./routes/index');
app.configure(function () {
app.use(express.static(__dirname + '/app'));
app.use('/css', express.static(__dirname + '/app/css'));
app.set('views', __dirname + '/app');
app.set("view options", { layout: false });
app.engine('.html', require('ejs').__express);
app.set('view engine', 'html');
app.use(express.favicon());
//app.use(require('connect').bodyParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
});
// Routes
app.get('/', routes.index);
app.get('/resetpassword.html/:resetcode', function (req, res) {
console.log("reset code: " + req.params.resetcode);
res.render('resetpassword.html/' + req.params.resetcode);
});
app.get('/api', function (req, res) {
res.send('Ecomm API is running');
});
// JSON API
app.post('/registeruser', usersApi.registerUser);
app.post('/api/login', usersApi.logIn);
app.post('/api/addgame', gamesApi.addGame);
app.get('*', routes.index);
// Start server
app.listen(2221, function () {
console.log("Express server listening on port %d in %s mode", 2221, app.settings.env);
});
and index.js
exports.index = function(req, res){
res.render('home.html');
}; // Always rending index.html which needs to be fixed.
And app.js from AnghularJs as follows
app.config(function ($routeProvider) {
$routeProvider
.when('/', { templateUrl: 'home.html' })
.when('/resetpassword.html/:resetcode', { templateUrl: '/resetpassword.html', controller: 'ResetPasswordCtrl' })
.otherwise({ redirectTo: '/' });
});
I am getting 500 internal error or view not found error.
Any suggestions please.
You are concatenating the password to the view name that you pass to render hence why Express does not find the view and returns a 500 error. You need to pass the data as an additional parameter to the render function as an object:
res.render('resetpassword.html', {resetcode: req.params.resetcode} );
Then in your view use resetcode directly e.g.
<span><%= resetcode %></span>
Instead of checking in every controller I want to use app.all('*') to check if the user is authenticated and it already works quite well. If the user is logged in I'm just calling next() and if he's not I'm calling another route to display the login page.
So far so good, but it seems that rendering from that middleware callback function somehow messes up my paths, for example the stylesheet doesn't work and when I click on it in the page source I again land on the index page.
To sum it up, this works and displays my styles:
app.get('/', function (req, res) {
res.render('index', { title: 'Account Page' });
});
while this does work partially, it only displayes the HTML without the styles from the stylesheet:
app.all('*', function (req, res) {
app.set('loggedIn', controller.security.authenticationAction(req));
if (app.get('loggedIn')) next(); // go on with '/' route
else res.render('index', { title: 'Index Page' });
});
This also displays the same HTML page (with another title though) just without the styles.
This is my default config in the app.js:
app.all('*', function (req, res) { ... });
// 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')));
app.use(express.cookieParser('keykeykey'));
Help!
Your stylesheets are (probably) served by express.static, which is declared after your app.all() route (with Express, whenever you first declare a route, the router middleware is inserted into the middleware chain there-and-then; in fact, using app.use(app.router) is useless most of the time, because Express has already inserted it behind the scenes).
Because requests are processed by middleware in order of their declaration, your app.all gets to handle the requests for static resources as well. Try moving the static middleware to before your app.all:
app.use(express.static(path.join(__dirname, 'public')));
app.all('*', function (req, res) { ... });
By the way, express.favicon() would probably give similar issues, and if you want to use any of the services provided by express.bodyParser or express.cookieParser etc., the same applies again).
I have some code that looks like the following:
app.configure(function() {
app.set("views", __dirname + "/views");
app.set("view engine", "ejs");
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.logger());
app.use(app.router);
app.use(express.static(__dirname + "/public"));
});
//Routes
app.get("/", function(req, res) {
res.render("index.ejs", {locals: {
title: "Welcome"
}});
});
//Handle 404
app.get("/*", function(req, res, next) {
next("Could not find page");
});
The problem I have is that I can't access anything in the /public static directory: everything gets caught by the 404 route. Am I missing something about how this is supposed to work?
You're doing
app.use(app.router);
app.use(express.static(__dirname + "/public"));
What you want to do is
app.use(express.static(__dirname + "/public"));
app.use(app.router);
Since you have a catch all route in app.router it must be lower then anything else. otherwise the catch all route will indeed catch everything and the rest of the middleware is ignored.
As an aside catch all routes like that are bad.
A better solution would be to place the following code after all calls to app.use:
app.use(function(req, res) {
res.send(404, 'Page not found');
});
Or a similar function.
Do this instead of using app.get("/*", ...
I'm doing it a slightly different way. If you look at the middleware code for the static file server it allows for a callback function that gets called with errors. Only catch is you need the response object to send something useful back to the server. So I do the following:
var errMsgs = { "404": "Dang that file is missing" };
app.use(function(req, res, next){
express.static.send(req, res, next, {
root: __dirname + "/public",
path: req.url,
getOnly: true,
callback: function(err) {
console.log(err);
var code = err.status || 404,
msg = errMsgs["" + code] || "All is not right in the world";
res.render("error", { code: code, msg: msg, layout: false});
}
});
});
Basically what happens is if there is an error it renders my pretty error page and logs something so that I can debug somewhere.