bmullan91 / express-subdomain

Super simple subdomain middleware for expressjs
415 stars 49 forks source link

Static content served on other subdomains #39

Open SplitPixl opened 6 years ago

SplitPixl commented 6 years ago

So I have run into a problem with content on subdomains that shouldn't be there being there.

Let's assume that I have a folder of static content that should only be served on example.com. In this folder I have a file foo.png

I will be using this code:

app.js:

// deps and stuff

app.use(express.static(path.join(__dirname, 'static')));

fs.readdirSync('./modules').forEach((mod, index, array) => {
  if(mod.endsWith('.js')) {
    let name = mod.substring(0, mod.length - 3)
    console.log(`Loaded module: ${name}`)
    app.use(subdomain(name, require(`./modules/${mod}`)))
  }
})

// other server stuff

modules/test.js

//deps n stuff

router.get('/', (req, res, next) => {
  res.send("Hi, this test worked.");
});

module.exports = router

I would expect http://example.com/foo.png to return the picture, which it does. I would also expect http://test.example.com/foo.png to return a 404 not found, but it returns foo.png as well.

How would I get my static content to only show on the domain example.com? I tried app.use(subdomain('', staticContentRouter)) but it throws an error.

yahiarefaiea commented 6 years ago

+1 Yep, I'm running into the same problem, too.

In addition, If you have a router in your root route. You can access the same route from any other subdomain if the route isn't in use for that subdomain.

I don't know if this issue exists when you deploy your project into a real server. But, it's there on localhost and it's really annoying.

knoxcard commented 6 years ago

I was about to submit a pull request and hack out a solution, then it dawned on me!

Here is the solution, sooo simple....

Place this line app.use(express.static(path.join(__dirname, 'static')));

before... express.Router()

Example

app.use(express.static(path.join(__dirname, 'static')));
app.dispensary = app.express.Router()
  app.use( require('express-subdomain')('dispensary', app.dispensary))
  require('fs').readdirSync('./controllers/').forEach(controller => {
    require('./controllers/' + controller)(app)
  })

:-)

knoxcard commented 5 years ago

Remember, the best way to serve static content is with NGINX, not NODEJS!

nginx.conf

    server {
        listen                              443 ssl http2;
        listen                              [::]:443 ssl http2;
        server_name                         static.indospace.io;
        ssl_protocols                       TLSv1 TLSv1.1 TLSv1.2;
        ssl_certificate                     /etc/letsencrypt/live/www.indospace.io-0022/fullchain.pem;
        ssl_certificate_key                 /etc/letsencrypt/live/www.indospace.io-0022/privkey.pem;
        ssl_dhparam                         /etc/nginx/dhparam_2048.pem;
        ssl_prefer_server_ciphers           on;
        ssl_ciphers                         "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";        
        ssl_session_timeout                 59m;
        ssl_session_cache                   shared:SSL:59m;
        ssl_session_tickets                 on;
        ssl_stapling                        on;
        ssl_stapling_verify                 on;
        #resolver                            8.8.4.4 8.8.8.8;
        #resolver_timeout                    5s;
        add_header                          Access-Control-Allow-Origin "*";
        add_header                          Access-Control-Allow-Headers X-Requested-With;
        add_header                          Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header                          X-Content-Type-Options "nosniff";
        add_header                          X-XSS-Protection 1;
        allow                               all;
        gzip                                on;
        gzip_http_version                   1.0;
        gzip_vary                           on;
        gzip_comp_level                     6;
        gzip_proxied                        any;
        gzip_types                          application/javascript application/rss+xml application/vnd.ms-fontobject application/x-font application/x-font-opentype application/x-font-otf application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/opentype font/otf font/ttf image/svg+xml image/x-icon text/css text/javascript text/plain text/xml;
        gzip_buffers                        16 8k;
        include                             /etc/nginx/mime.types;
        location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js|scss|map|less|woff|woff2|otf|eot|ttf)$ {
            expires                         30d;
        }
        fastcgi_hide_header                 Set-Cookie;
        root                                /etc/nginx/www/static;
    }
tavindev commented 4 years ago

To solve this is simple, just add app.set('subdomain offset', 1) to your "server.js" file.

This happens because the subdomain offset is set to 2 by default. Therefore any request to example.localhost will not work because example and localhost don't count as subdomains. However, requests to api.example.localhost would work because api would count as a subdomain.

When setting the offset to 1 example counts as a subdomain, resolving this problem

mateimarica commented 1 month ago

The subdomain offset is unrelated to this problem, OP showed he isn't using localhost. Either way, when testing subdomains, it's best to setup your hosts file and resolve using the actual TLD.


This is simple fix, just don't allow the request to propagate out of the subdomain router.

app.js

const express = require('express'),
      path = require('path'),
      subdomain = require('express-subdomain'),
      xyz = require('./xyz');

app.use(subdomain('xyz', xyz)); // register the subdomain routers first
app.use(express.static(path.join(__dirname, 'static/directory/path')));

// ...


xyz.js

const express = require('express'),
      router = express.Router();

// put all the middleware and routing here

router.use('*', (req, res) => {
      res.sendStatus(404);
});

module.exports = router;

Now, a static file such as example.com/script.js will return a 404 at xyz.example.com/script.js