Expressjs remove static folder - node.js

I have nodejs webpage and i am using expressjs. I have few static folders and with user log out i have to remove some of them. Below is how i add static folder, i am not using any options maybe that is the problem.
app.use(express.static(__dirname + '/public'));
And i need something like below:
app.use(express.removeStatic(__dirname + '/public'));
or
app.use(express.static(__dirname + '/public',{vissible: false}));

As described here the express.static middleware is based on serve-static. There is no way of removing already loaded middleware (static files).
What I would suggest is creating your own serve-static middleware. You can use this as reference then just load the session middleware before the serve-static middleware then add an option that checks if the session data is available, if not then don't serve.
The basic idea is something like:
return function serveStatic(req, res, next) {
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next()
}
// add this
if (req.session.loggedIn === false) {
return next()
}
Example
I have copied the serve-static code and added a condition to it, you can get it here.
Download it and save it as serve-static.js.
Include it in your expressjs project.
Modify to your use case.
Beware untested code.
Usage
var static = require('./serve-static')
// session middleware here
app.use(static(__dirname + '/public'));
This should only serve the static files when the req.session.loggedIn is true.
Of course you can change the condition to anything you want like:
if (req.session && req.session.ANYTHING_I_WANT === false && !!someMore) {
// skip all the code below (will not serve)
return next()
}
The condition can be found on line 64 of my serve-static gist.
Remember to add the session middleware before using the static middleware.

You can't remove static folders from express. What you can do is use res.sendFile to send a file as the response. For example:
app.get('public/:filename', function(req, res){
if(user.loggedIn) {
res.sendFile(req.params[:filename]);
} else {
res.status(402).send("Log in to access file");
}
})

Related

ExpressJS Serve static files within request function

I'm currently serving static files like this:
app.use('/javascripts', express.static(join(__dirname + '/assets/javascripts')));
and it works as expected.
What I would like to do is to use the user session to serve static files depending on the session. I've tried this:
app.use('/javascripts', (req: Request, res: Response, next) =>{
if(req.session.auth){
express.static(join(__dirname + '/auth/javascripts'))
} else{
express.static(join(__dirname + '/assets/javascripts'))
}
});
but it doesn't serve the files. Can someone explain why it doesn't work and how I can achieve what I'm trying to do?
A middleware function (the second argument of .use()) should process the request and call next(), so this code does nothing.
What you need is to just have a dynamic route (instead of middleware) that redirects to the correct static directory according to req.session.auth:
app.get('/javascripts/*', function(req, res){
if(req.session.auth){
res.sendfile(req.params[0], {root: './auth/javascripts'});
} else {
res.sendfile(req.params[0], {root: './assets/javascripts'});
}
});

Exclude sub directory from static files in express

Is there any way to exclude sub directory from express static middleware in express 4.8.5.
For example if I have :
app.use(express.static(__dirname + 'public'));
And my public directory is like this :
- public
- css
- images
- scripts
- index.html
- exclude_me
- scripts
- views
- index.html
So I need to exclude last sub directory and when user does :
GET /exclude_me
It should call my route rather than returning directory automatically.
I can't just remove it from public dir because it depends on stuff inside it because public directory is angular application and exclude_me is another angular application that fetches scripts from /exclude_me/scripts AND from /public/scripts.
I know it is little confusing but it is how it is and I cannot just remove it from public dir because it won't see public/scripts any more which are needed and I cannot leave it because I cannot authorize it then (all authorization is in public/scripts)
If there is some smarter way to do this, feel free to let me know :)
You can add your own middleware. Here's what I did to exclude some folders:
app.use('/public', (req, res, next) => {
if (env !== 'development') {
var result = req.url.match(/^\/js\/(maps|src)\/.+\.js$/)
if (result) {
return res.status(403).end('403 Forbidden')
}
}
next()
})
app.use('/public', express.static(path.join(__dirname, '/public')))
It's possible by adding regular expressions to the first optional param of use method.
According with Express 4.x API path documentation.
Example, I don't want to give access to my secure folder inside public folder:
var express = require('express');
var app = express();
app.use([/^\/public\/secure($|\/)/, '/public'], express.static(__dirname + '/public'));
This will allow you to access all files but not the ones in the secure folder.
You can use it also to restrict a file extension, example files that ends with .js.map:
app.use([/(.*)\.js\.map$/, '/public'], express.static(__dirname + '/public'));
And you also can add multiple rules, like this example where secure folder and files that end with .js.map are ignored from the static folder:
app.use([/^\/public\/secure($|\/)/, /(.*)\.js\.map$/, '/public'], express.static(__dirname + '/public'));
I had a similar problem, which may be the answer you were seeking. Given the following directory:
public
css/
images/
secure/
index.html
The Express Middleware stack I wanted was this:
1. Static files (except the `secure/` directory)
2. Logging
3. Authentication
4. `secure/` static files
Here's how I solved it:
var express = require('express');
var path = require('path');
var app = express();
// path.join here makes it work cross platform with Windows / Linux / etc
var statics = express.static(path.join(__dirname, 'public'));
function secureStatic(secure) {
return function (req, res, next) {
if (/^\/secure/.test(req.path) === !!secure) return statics(req, res, next);
return next();
};
}
// add public files
app.use(secureStatic());
app.use(logging());
app.use(authentication());
// add secured files
app.use(secureStatic(true));
This will only serve public files when unauthenticated, and only serve secure files after authentication.
Most solutions above are to use a middleware.
However, there is a just easier way to solve this.
Don't serve static assests directly with the dir public rather than serve dir just what you want to serve with a virtual path prefix .
You can serve like below
var express = require('express');
var app = express();
app.use('/public', __dirname + 'css');
app.use('/public', __dirname + 'images');
...

Serve out 'static' route with express with redirect and middleware

I am serving out a static url with express 4.0:
app.use('/static-route', express.static('./static'));
And that works great.
However I would like to redirect my users to a url with a query parameter if they hit that route.
ie /static-route -> /static-route?someQueryParam=hello
I would also like to include middleware for that static request. As a concrete example I am using passport and would like to make sure the user is logged in to access that static content.
app.use (and app.get etc . . .) doesn't take two parameters, the first parameter is the route (optional for use), then the rest are all middleware.
app.use('/static-route', function (req, res, next) {
// validation
// redirect
// etc . . .
next();
}, express.static('./static'));
Use global wilcard route[ app.use('/') ] for static content and
Use specific routes [ app.get(/myroute), app.post('/anotherroute')] for dynamic processing using custom logic
//Serves resources from public folder
app.use('/',express.static(__dirname + '/public'));
//Verify the complete directory path - especially slashes
console.log('Static directory '+__dirname + '/public');
app.get('/list', function (req, res) {
res.send('<html><body><h1>Hello World</h1></body></html>'); });

Common Pre-Handler for ConnectJS/ExpressJS url handlers?

In my ExpressJS app, several of my urls handlers have the following logic:
See if the user has permission to access a resource
If so, continue
Else, redirect to the main handler.
Is there a way to insert a pre-handler for certain url handlers, via ConnectJS or ExpressJS?
I know I can do it globally, for all handlers, (which I do to insert missing headers as a result from IE's broken XDR).
But, can I do this for a subset of handlers?
I do something like this:
lib/auth.js
exports.checkPerm = function(req, res, next){
//do some permission checks
if ( authorized ) {
next();
} else {
res.render('/401');
return;
}
};
app.js
var auth = require('./lib/auth');
...
app.get('/item/:itemid', auth.checkPerm, routes.item.get);
You can stack middleware before your final route handler like the above line has. It has to have same function signature and call next();
If I understand this question correctly, you know about:
// This is too general
app.use(myAuthMiddleware());
And you are aware that you can add it manually to certain url-handlers:
app.get('/user/profile/edit', myAuthMiddleware(), function(req,res){
/* handle stuff */ });
// but doing this on all your routes is too much work.
What you might not know about express' mounting feature:
// Matches everything under /static/** Cool.
app.use('/static', express.static(__dirname + '/public'));
Or app.all():
// requireAuthentication can call next() and let a more specific
// route handle the non-auth "meat" of the request when it's done.
app.all('/api/*', requireAuthentication);

More sophisticated static file serving under Express

Best explained by an example. Say I have a directory /images, where I have images a.png, b.png, and c.png.
Then I have a directory /foo/images, which has an image b.png, which is different than the b.png in /images.
I want it so if a request comes in for http://mydomain.com/foo/images/a.png, it will serve the image /images/a.png. But if a request comes in for http://mydomain.com/foo/images/b.png, it will get the version of b.png in /foo/images. That is, it first checks foo/images/ and if there is not file by that name, it falls back on /images.
I could do this using res.sendfile(), but I'd prefer use built-in functionality if it exists, or someone's optimized module, while not losing the benefits (caching, etc) that might be provided by the middleware.
This would intercept requests to /foo/images/ and redirect them if the file doesn't exist, still using static middleware and caching appropriately
var imageProxy = require('./imageProxy.js');
// intercept requests before static is called and change the url
app.use( imageProxy );
// this will still get cached
app.use( express.static(__dirname + '/public') );
And inside imageProxy.js:
var url = require('url');
var fs = require('fs');
var ROOT = process.execPath + '/public';
exports = function(req, res, next) {
var parts = url.parse(req.url);
// find all urls beginnig with /foo/images/
var m = parts.pathname.match(/^(\/foo(\/images\/.*))/);
if( m ) {
// see if the override file exists
fs.exists(ROOT+m[1], function (exists) {
if( !exists ) { req.url = ROOT+m[2]; }
// pass on the results to the static middleware
next();
});
}
});
If you wanted to access the original URL for some reason, it's still available at req.originalUrl

Resources