7
app.get("/:name?/:group?", function(req, res){...

is matching files that are in my public directory. So if I include a stylesheet:

<link type="text/css" href="/stylesheets/style.css" />

Node will match /stylesheets/style.css and assign name the value stylesheets and group the value style.css.

What's the best way to avoid this?

Luke Burns
  • 1,911
  • 3
  • 24
  • 30

3 Answers3

23

The easiest thing may be to make sure that express runs the static provider middleware prior to the router middleware. You can do this by doing:

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

That way the static file will find it and respond and the router won't be executed. I've had similar confusion with the router's default position (last) screwing up with my compilation of coffeescript files. FYI there are docs on this here (search the page for app.router and you'll see an explanatory paragraph.

Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
  • 1
    I think the Express API has changed since this answer was posted. The syntax that works for me is: app.use('/public', express.static(__dirname + '/public')); I also didn't need the app.router line. – ashack Jan 21 '14 at 17:49
  • 1
    @ashack that all depends on whether you want `/public` in your URLs, your filesystem, or both. Generally `public` is the name of a filesystem directory but does not appear as part of the URL. Whether you need the explicit line about `app.router` also depends on how your other calls to `app.get` and friends are ordered/organized. – Peter Lyons Jan 21 '14 at 19:48
  • This worked for me in the scenario where I had an `app.get("/*", function(req, res) {})` to catch "direct" url requests and page reloads etc, but I didn't want it to be handling the subsequent page requests for css, js, img files. I put `app.use(express.static("public"));` above it, and the catchall no longer handled those requests. – user1063287 May 13 '18 at 12:00
  • @PeterLyons This will not work in all cases actually - https://stackoverflow.com/questions/58375400/exclude-public-folder-from-express-router – loretoparisi Oct 14 '19 at 13:17
2

For anyone who may need it, my solution was using Middleware. If anyone finds a better solution, please let me know!

public = ['images', 'javascripts', 'stylesheets', 'favicon.ico']

ignore = (req, res, next) ->
    if public.indexOf(req.params.name) != -1
        console.log "Ignoring static file: #{req.params.name}/#{req.params.group}"
        next('route')
    else
        next()

app.get "/:name?/:group?", ignore, (req, res) -> ...
Luke Burns
  • 1,911
  • 3
  • 24
  • 30
2

You could also have a reverse proxy like Nginx handle the static files for you. I believe many professional Node / Ruby on Rails setups do it this way.

Mauvis Ledford
  • 40,827
  • 17
  • 81
  • 86
  • 1
    In production yes, this is the way to go. Generally you still want to set this up in express as well for local development purposes. Generally people don't bother with a reverse proxy during local development, but you still need something to serve your static files. – Peter Lyons Jan 21 '14 at 19:52