Using middleware with express().use along with express.static - node.js

I'm using PassportJS to secure a WebApp (written with AngularJS). I'm using NodeJS with Express (4.0.0) to serve static content after the login-screen. I don't get how to use a middleware along with express.static() at the same time.
My (not working) code looks like
app.use('/secure',
function (req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
},
express.static(__dirname + '/../../client'));
The plan is, that the middleware ensures, that the user is only forwareded to the WebApp if he/she is logged in. If not, he/she/it is redirected to the root folder.
I found this answer, but according to the documentation, the new version supports multiple functions. This isn't the "clean" solution I'm looking for, since the directory contains too many subfolders and files.
Thanks in advance

When you attach middlewares to the same route they get executed in the same order of declaration, so if you want to execute any middleware before express.static, all what you have to do is attach it to the same route and declare it before.
app.use('/secure', myMiddleWare);
app.use('/secure', express.static(__dirname + '/../../client'));

Related

router.param not triggering passport.js initialize in app.use

I've got a fairly straight forward Node Express routing app set up, to which I've just added passport.js authentication. I'm now trying to integrate this with the existing routes.
I run the basic middleware of:
app.use(passport.initialize());
app.use(passport.session());
and then if I run a simple
app.get('/route', (req, res)=>{
console.log(req.user)
});
I get the expected result of it printing the logged in user. So far so good...
However, I'm now trying to access this req.user within some of the child routes that I have set up. In the first route I'm trying the first step is to bring in a parameter and compare it against the req.user:
app.use('/route/:userId', idRouter);
And then:
idRouter.param("userId", async (req, res, next, userId) => {
console.log(userId)
console.log(req.user.id)
})
This route fires and prints out the parameter, but req.user is undefined. I can't see a reason why this is the case.
To help debug this I've put some logging in the deserialize function and I can see that it's not being called when I hit the idRouter. I can't see why this would be the case given it's inside an app.use function which should be called every time.
Help please!
I solved this in the end, it was an issue with CORS. Just needed to include credentials in API calls.

How to serve user specific static content in Express.js

I want to serve user-specific static content in Express. That means, if a user is logged in, his private static folder is served by express. Other users shall not have access.
I tried the following (see below), but the static content is not being served. In fact, the route seems to be completely ignored and I get a 404.
I am not sure if the way I do it is the right way to go and if express is capable of dynamically serving different static folders. Thanks in advance for your thoughts on this.
Here's the code (simplified):
routes.js:
express = require 'express'
router = express.Router()
router.use '/user/assets', (req, res, next) ->
if req.user
userpath = 'uploads/' + md5(req.user._id)
if not fs.existsSync userpath
fs.mkdirSync userpath
console.log "Created user directory at " + userpath
express.static(userpath)
next()
module.exports = router
index.js:
express = require 'express'
app = express()
app.use '/', require './routes'
Sidenotes:
The md5 is just a way of escaping weird characters in the user id, which is a string. I know there is a possibility for a mismatch, which is tiny, and about which I don't wanna care for now. Concerns about general security of the fashion of the solving attempt are appreciated.
The code is written in CoffeeScript.
req.user contains a valid user element.
Just calling express.static is not enough, you need to use() it with the router. Unfortunately you can't directly do that, since you require a different set of routes for each user.
Calling express.static will return a middleware function. You could call it directly, i.e. something like this:
var files = express.static(userpath);
return files(req, res, next);
However that's still not enough, as the middleware uses req.url to build the file path. The express router adjusts this property and removes the mount point (see req.originalUrl in the docs). So you need to strip /user/assets from it, before calling the middleware.
By the way, you should set the DEBUG environment variable for node. It allows you to see what routes are created by express, which is very handy in debugging express.static 404 problems. E.g. you'd do $ DEBUG=* node index.js on Linux.
As you can see the approach starts to be a bit hacky and creating a new express.static middleware on each request is not very performance friendly too. So depending on what your user directories contain, using res.sendFile might actually be better.
As a sidenote, I assume you've checked that req.user actually contains something if the user is logged in.

Express middleware refrain static from going into next

I have the following function:
app.use('/Framework', express.static(path.resolve(__dirname, 'Framework')));
app.get('/*/*', function (req, res, next) {
...code...
);
The request goes into both the app.use and the app.get. I'd like it that when I try to access a resource with /Framework it just gives it to me as static while ignoring the other functions from below. Yet when accessing static it seems to go in the app.get.
Why is this happening and how can I modify it to get the wanted behavior?
Edit due to comment
I also have a
app.use('/Public', express.static(path.resolve(__dirname, 'Public')));
before which works perfectly as expected.
Requests such as : /Public/0.png work while requests such as /Framework/0.png enter both functions. I have checked the folders names over and over again and they are correct.
Express-static is Express middleware. Middleware is chained together and after a middleware is done executing its code, it calls next(); internally to allow the next middleware to execute. After all middleware is executed, the routes will be executed.
Since express-static calls next(); after its done, the routes will be invoked and checked if any routes match the request. Since your request /Public/0.png matches your route /*/* the route is executed.
My suggestion would be to try an rename your route from /*/* to something more specific.
You could try regex for the route which would explicitly allow any requests matching /*/* but would refuse any routes which have a file extension appended to it (i.e. /*/*.png).
Another (hacky) way would be to check for headersSent inside your /*/* route before executing the code within that route.
A side-note:
Seeing how your route name (e.g. Public and Framework) are the same as your directory names, you could simply do
app.use('/', express.static(path.resolve(__dirname, PARENT_DIRECTORY)));
Where PARENT_DIRECTORY is the parent directory of both Public and Framework. This way
Your directory structure would look like this:
Directory
|
| ---- Public
| ---- Framework
And any requests to Public would end up serving files from your Public directory, same for the Framework directory respectively.

express.js - use middleware for non static urls only

How do i create middleware that runs on all urls that arent serving static files?
i was thinking of checking if req.url doesnt start with "/js/", "/css/" or "/images/" but there must be a better way
The easiest (and fastest) way is to put your static file middleware ahead of your 'catch all' middleware:
app.use(express.static(STATIC_DIR_HERE));
app.use(function notStatic(req, res, next) {
// everything here will be non-static routes
});
(where app is your express instance)

How to use AngularJS routes with Express (Node.js) when a new page is requested?

I'm using Express, which loads AngularJS from a static directory. Normally, I will request http://localhost/, in which Express serves me my index.html and all of the correct Angular files, etc. In my Angular app, I have these routes setup, which replace the content in an ng-view:
$routeProvider.when('/', {
templateUrl: '/partials/main.html',
controller: MainCtrl,
});
$routeProvider.when('/project/:projectId', {
templateUrl: '/partials/project.html',
controller: ProjectCtrl,
});
$locationProvider.html5Mode(true);
On my main page, I have a link to <a href="/project/{{project.id}}">, which will successfully load the template and direct me to http://localhost/project/3 or whatever ID I have specified. The problem is when I try to direct my browser to http://localhost/project/3 or refresh the page, the request is going to the Express/Node server, which returns Cannot GET /project/3.
How do I setup my Express routes to accommodate for this? I'm guessing it will require the use of $location in Angular (although I'd prefer to avoid the ugly ?searches and #hashes they use), but I'm clueless about how to go about setting up the Express routes to handle this.
Thanks.
with express 4, you probably want to catch all requests and redirect to angularjs index.html page.
app.use(app.router); doesn't exist anymore and res.sendfile is deprecated, use res.sendFilewith an uppercase F.
app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
res.sendFile('/public/index.html');
});
put all your API routes before the route for every path app.get('*', function (req, res){...})
I would create a catch-all handler that runs after your regular routes that sends the necessary data.
app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/public/index.html');
});
app.router is the middleware that runs all of your Express routes (like app.get and app.post); normally, Express puts this at the very end of the middleware chain automatically, but you can also add it to the chain explicitly, like we did here.
Then, if the URL isn't handled by app.router, the last middleware will send the Angular HTML view down to the client. This will happen for any URL that isn't handled by the other middleware, so your Angular app will have to handle invalid routes correctly.
I guess I should have clarified that I wasn't interested in using a template engine, but having Angular pull all of the HTML partials on it's own, Node is functioning completely as a static server here (but it won't be for the JSON API. Brian Ford shows how to do it using Jade here: http://briantford.com/blog/angular-express.html
My app is a single-page app, so I created an Express route for each possible URL pattern, and each of them does the same thing.
fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
res.send(content);
});
I was assuming I would have to pass some request variables to Angular, but it looks like Angular takes care of it automatically.

Resources