Ivan Longin
Ivan Longin

Reputation: 3353

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 :)

Upvotes: 23

Views: 16521

Answers (4)

Gabriel Gartz
Gabriel Gartz

Reputation: 2870

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'));

Upvotes: 16

Fan Yer
Fan Yer

Reputation: 393

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');
...

Upvotes: 2

Rivenfall
Rivenfall

Reputation: 1263

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')))

Upvotes: 18

Dan Crews
Dan Crews

Reputation: 3597

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.

Upvotes: 5

Related Questions