I am attempting to send all GET requests on my site (other than API requests) to a controller which checks for the presence of a signed-in user before showing the page. Otherwise, if not currently signed in, the user is sent to the sign-in page.
The below structure works perfectly for everything but the root route ('/'). For example, if I try to hit /admin or /games as a non signed-in user I am properly sent to the sign-in page. Likewise, if I am signed in each page shows properly (note: I am using AngularJS client-side). The one issue I have is that when I hit my root route the app attempts to show index.html without ever checking if the user is signed in. I'm confused as to why that route is handled differently, and why my pagesController is seemingly never invoked for this route. I've done some 'console logging' and confirmed that pagesController.index is called for each non-API route but '/'.
routes.js
'use strict';
var controllers = require('./controllers');
var v1Router = require('./routes/api/v1');
var pagesController = controllers.pagesController;
module.exports = function(app) {
app.use('/api', v1Router);
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
app.get(['*'],
pagesController.index
);
};
pages.js
'use strict';
var path = require('path');
var index = function(req, res) {
if (req.user) {
res.sendFile(path.join(__dirname, '../assets', 'index.html'));
} else {
res.sendFile(path.join(__dirname, '../assets', 'signin.html'));
}
};
module.exports = {
index: index
};
Update: I changed my root from / to /a in my client-side routing and everything works perfectly. For whatever reason / is not being run through pagesController.index.
Update 2: So this line in my app.js is causing the issue:
app.use(express.static(path.join(__dirname, 'assets')));
With that line removed pagesController.index is properly called on /, however none of my static assets are served so simply removing that line does not solve it. How can I serve my static assets properly while ignoring index.html?
You can also handle the route in your conditional statements:
'use strict';
var path = require('path');
var index = function(req, res) {
if (req.user) {
res.sendFile(path.join(__dirname, '../assets', 'index.html'));
} if (req.url === '/') {
** Handle Case Here **
}
else {
res.sendFile(path.join(__dirname, '../assets', 'signin.html'));
}
};
module.exports = {
index: index
};
Ok, I did some research: A great article and possible solution here:(not sure if it fits your use case)
http://evanhahn.com/express-dot-static-deep-dive/
app.use(express.static(myStaticPath, {
index: ['jokes.txt', 'index.html']
})
You can simply give an array of files to serve as index, if the first is found it is served, if not, the second is served, and so on.
Related
I have html pages which shouldn’t be seen by the users who haven’t logged in. I used the command below and my html pages became public.
app.use(express.static('public'));
For example, I do not want users who are not logged in to see this page.
http://localhost:3000/admin.html
NOTE: what I'm talking about is not a cookie. When you enter the address of the html page in the toolbar, if it is not logged in, it should not be able to reach that page.
Create a custom static middleware, with the middleware you can validate the path(filename for this case).
I will try to explain with comments in a example code:
// path.join here makes it work cross platform with Windows / Linux / etc
var statics = express.static(path.join(__dirname, 'public'));
function secureStatic(pathsToSecure = []) {
return function (req, res, next) {
if (pathsToSecure.length === 0) {
return statics(req, res, next); // Do not secure, forward to static route
}
if (pathsToSecure.indexOf(req.path) > -1) {
return res.status(403).send('<h1>403 Forbidden</h1>'); // Stop request
}
return statics(req, res, next); // forward to static route
};
}
// add public files. List all "private" paths (file)
app.use(secureStatic(['admin.html'])); // instead of app.use(express.static('public'));
But, with this middleware, no one can request to admin.html file via you express server.
I am developing an application and I have defined my custom routes in a different way. I am using Web Storm IDE to develop and it has a specific folder of routes where all the routes are kept individually. I have the following code in my directory /routes/about.js file:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('about', { title: 'About Us' });
});
module.exports = router;
Now in the app.js I have written the following code to include these route and use it:
var index = require('./routes/index');
var users = require('./routes/users');
var about = require('./routes/about');
app.use('/', index);
app.use('/users', users);
app.use('/about', about);
But when I click on about link, it does not open the page. Though, if I write the route in the app.js file directly as:
app.get('/about', function (req, res) {
res.render('about');
});
then it renders the page. Also, if I do not make separate routes and use the default routes file (/routes/index.js) and include this in that file, then also the code works fine. Can anyone explain or tell is there any mapping of these route files done which is missed by me, or I am doing something syntactically wrong
You probably created a route for /about/about. To fix, change the about router from this:
router.get('/about', ...);
to this:
router.get('/', ...);
This, then goes with:
app.use('/about', router);
which already includes the /about path. Everything in that router will already have /about at the beginning of the path.
Use below code in about file
app.get('/', function (req, res) {
res.render('about');
});
You have already defined '/about' route in main file so if you want to render page on '/about' so you need to define route like this '/' in about page.
For example route '/about/us' then function will be in about page :
app.get('/us', function (req, res) {
res.render('about us');
});
The method to redirect the route is correct, but you have not pass the route to app.
so you just need to do is ,
router.use('/about', about);
app.use('/', router);
Like wise add router in app
Introduction
I have built some back end functionality in Node (First time using Node). Problem is that the whole thing was built in one page (index.js) so now im following a few basic tutorials and setting out express router middleware and now trying to follow a modular MVC approach,
This code is simple but brakes when I separate into two pages Server.js and config.js. I know its a simple problem but i cant spot it. can someone help spot the problem and maybe improve the structure ?
Problem
I go to http://localhost:8080/about or a different route and I get
Cannot GET /about
rather than the correct print out.
back-end/server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
// get an instance of router
var router = express.Router();
// START THE SERVER
// ==============================================
app.listen(port);
console.log('Server has started!! ' + port);
back-end/config.js
router.use(function(req, res, next) {
console.log(req.method, req.url);
next();
});
router.get('/', function(req, res) {
res.send('im the home page!');
});
// sample route with a route the way we're used to seeing it
router.get('/sample', function(req, res) {
res.send('this is a sample!');
});
router.get('/about', function(req, res) {
res.send('im the about page!');
});
app.route('/login')
.get(function(req, res) {
res.send('this is the login form');
})
.post(function(req, res) {
console.log('processing'); // shows on console when post is made
res.send('processing the login form!'); // output on postman
});
app.use('/', router);
As #SLaks said in his comment, you need to import (require) your backend/config.js file. But it's not as simple as that...
In node, variables are scoped to the file in which they appear, so if you simply add require('./config') to your server.js file, that's not going to work either, because the router variable in config.js is local to that file - it's not going to know about the router variable in server.js.
The solution to this is to have the config.js file export a function which the server.js file can use to configure stuff. For example
config.js
module.exports = function(router) {
// set up your router here with router.use, etc.
};
server.js
var configure = require('./config');
// after you set up your express router...
configure(router);
// now start listening
I'm trying to get my express app to always return 'index.html' which is the layout file that contains my angular app scaffold.
In my angular app when i'm at route "/home" I want to be able to refresh the page, so to do that I need my router to return me index.html.
For my html routing i'm using the following - All of my templates (home.html) are stored in the /templates directory:
var express = require("express"),
router = express.Router(),
path = require("path"),
root = path.join(__dirname, "../../");
router.use(express.static(__dirname + "/../../templates"));
router.get("*", function(req, res) {
//Response options
var options = {
root: root,
};
res.sendFile("layouts/index.html", options);
});
This is obviously affecting my REST API requests, in that they're not sending back index.html.
For example, I have an /islands api route which returns back 'Island' objects from my mongo db.
var router = require("express").Router(),
Island = require("../../model/island");
router.get("/", function (req, res, next) {
Island.findOne({user_id: req.user.email}, function (error, island) {
if (error) { return next(error); }
return res.json(island);
});
});
This is now returning me index.html.
Here's how i'm using the controllers above incase that helps.
app.use(require("./controllers/api/static")); //Returning static assets
app.use(require("./controllers/api/views")); //This is where the get route for returning .index.html is stored
app.use("/api/island",require("./controllers/api/island"));
I'm a little confused as to how I can get index.html only return for html requests, not requests made to my api.
Check order of your routes, put the api routes before your sendfile ones.
I'm using express framework 4.0 for my node js server . I was wondering if there was any way to remove routes dynamically at runtime
var express = require('express');
var router = express.Router(/*Options */);
router.get('/', function (req, res)
{
res.render('index', {title: "Home"});
});
router.get('/features', function (req, res)
{
res.render('features', {title: "Features"});
});
//Hook into the routing system
module.exports = function(app,rootPath)
{
app.use(rootPath, router);
};
This is a trivial example, but how could I remove the /features path from the routing table?Additionally is it possible to overwrite this routing path with another should I wish to update the features routing path at a later date ?
AFAIK you can't delete a route dynamically (at least not in a nice way), but you can use a filtering middleware to disallow access to a route when a certain condition is set.
For example:
var allowRoute = true;
var filterMiddleware = function(req, res, next) {
if (allowRoute !== true) {
return res.status(404).end();
}
next();
};
app.get('/features', filterMiddleware, function(req, res) {
res.render('features', { title: 'Features' });
});
You toggle allowRoute to enable or disable access to the route (obviously, depending on the exact use case you could also use properties in req to enable/disable access to the route).
A similar setup could be used to overwrite the route handler with another one, although I'm beginning to wonder what you are trying to accomplish and if overwriting route handlers is the solution for that.