13

I want a route called 'main' which will serve static files:

app.use('/main',express.static(__dirname+'/public'));

However when i do:

http://my.site.dev/main

The CSS and JS files won't download because it is trying to get them from

http://my.site.dev/css/styles.css

It should be getting the files from:

http://my.site.dev/main/css/styles.css

However, if I access my site with a trailing slash:

http://my.site.dev/main/

All files come through fine

Any ideas why not having a trailing slash messes up resources like CSS and JS from coming in?

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
Abadaba
  • 1,456
  • 7
  • 20
  • 30

2 Answers2

22

This is an http problem, not just an Express-related challenge. The problem is discussed at:

If your URL is /main and your relative URL is css/style.css, it will resolve to /css/style.css; but if your URL is /main/, the relative URL resolves to /main/css/style.css.

My strategy for dealing with this is to redirect to add the trailing slash. Like this in Express:

app.all(/^\/main$/, function(req, res) { res.redirect('/main/'); });
app.use('/main/',express.static(__dirname+'/public'));

Or:

app.enable('strict routing');
app.all('/main', function(req, res) { res.redirect('/main/'); });
app.use('/main/',express.static(__dirname+'/public'));
Community
  • 1
  • 1
Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
  • To redirect all routes without trailing / to the same url with trailing / you can use: app.use(/.*[^\/]$/, function (req, res, next) { res.redirect(req.originalUrl+'/'); }); The regex `/.*[^\/]$/` will match all urls without trailing / PS: If someone can fix my markup, please do. I don't know why my code is not in a code block – JayTheKay Feb 25 '16 at 16:48
  • I didn't have any luck with @kel's comment. It ended up producing one route that worked and one that didn't which was identical to the working route plus a trailing slash for all static content. Trevor's answer seems to work however. – mez.pahlan Feb 02 '17 at 15:50
2

How are the JS/CSS files requested in the HTML? If you're using strings like css/styles.css, then it will try to get them from the current directory. The directory for /main is / (just like /main.html would be), while the one for /main/ is /main/. A quick fix would be to use /main/css/styles.css in your HTML.

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • I'm using: It doesn't make sense to use the full path in the link href – Abadaba Jun 03 '12 at 05:16
  • 2
    Personally I always use full paths for assets as I never debug using the `file://` protocol. At any rate, you're limited to a few options here: (1) use the full path to the assets; (2) use a middleware or something in Express to ensure that a trailing slash always exists; (3) use a local when you render to tell your layout which path to use, e.g. in Jade `link(href="#{subdir}/css/styles.css")` (4) use `` in the HTML to set the base URI manually (seems like the worst solution). – Michelle Tilley Jun 03 '12 at 05:31
  • im not using the file:// protocol, my site is hosted locally with http://my.site.dev/main – Abadaba Jun 03 '12 at 06:42
  • If that's the case, why wouldn't it make sense to use the full path? If you use a relative path, you'll get different results for every subpath (e.g., relative paths from `/main`, `/main/something`, and `/main/something/else` are all different). – Michelle Tilley Jun 03 '12 at 07:26
  • In apache you can provide an alias in the conf file that points a path off the main url to a directory in the filesystem. You don't ever need to mention the alias path name in your script includes because root always points to that directory. I want the same functionality in node.js/connect/express with the non trailing slash. Im thinking it's some regex thing or i need to redirect main to main/ ? – Abadaba Jun 03 '12 at 16:53