10

NOTE: Turns out my issue isn't the middlware express.static(), but rather the difference between app.use() and app.get(). This question answers it perfectly (way better than the express API docs!):

Difference between app.use and app.get in express.js

I understand the difference between app.use('/') and app.get('/') to be that the latter only serves HTTP GET requests to that endpoint, while the former serves ALL HTTP requests to that endpoint.

I also understand that express.static middleware serves static pages from a directory path to an endpoint.

What I don't follow is why this:

app.get('/', express.static(__dirname + '/public')

Serves only the first page requested, and not any of the ref= or src= link/script pages referenced by the requested page. For example, here are two morgan traces responding to a simple index.html page that has a css link to file 'style.css'

1) Server request trace using app.use('/')

Server listening on 0.0.0.0:8080
GET / 200 6.258 ms - 444
GET /style.css 304 2.842 ms - -

2) Server request trace using app.get('/')

Server listening on 0.0.0.0:8080
GET / 304 5.131 ms - -
GET /style.css 404 2.990 ms - 22

404???

How is it that even though the browser sent a GET request to '/', app.get('/') failed to serve the css, but app.use('/') succeeded.

What detail am I missing with app.get('/') or express.static?

Thanks in advance, PT

Here's the simple, simple code:

app.js:

var morgan = require('morgan'),
    express = require('express'),
    app = express(),
    server = require('http').Server(app);
app.use(morgan('dev'));

   // Uncomment .get or .use, but not both

   // this only serves index.html, not style.css when I nav to localhost:8080/
   //app.get('/', express.static(__dirname + '/pub'));

   // this serves both pages when I nav to localhost:8080/
   app.use('/', express.static(__dirname + '/pub'));

server.listen(8080);

And here's the html...

index.html

<!doctype html>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
</html>

Path:

/app.js
/pub/index.html
/pub/style.css
Community
  • 1
  • 1
PeterT
  • 920
  • 8
  • 20
  • 1
    If you have things in the right order and the content is present in the appropriate directory and you have no errors, then per the [Express documentation](http://expressjs.com/api.html#express.static), this should work: `app.use(express.static(__dirname + '/public'));`. But, you will have to be very careful about the order of things. That's the usual reason that static content is put into a separate path so the middleware and `.get()` handlers are easier to separate out with a path designation (e.g. server all static content from a URL path of `/lib` or something like that. – jfriend00 Nov 27 '14 at 02:34
  • How does that relate to the question though? I don't understand the answer. It works fine with .use(). There are only two files in "public/" and one endpoint, "/". Shouldn't .use and .get both be responding to the browser's GET the same way? What's the difference? – PeterT Nov 27 '14 at 02:50
  • Then, I guess I don't understand what problem you're trying to solve? It isn't clear to me what URLs you want to generate what response. Please show some examples. – jfriend00 Nov 27 '14 at 03:17
  • @jfriend00 Let me explain a little more, and I might be using some of the terms incorrectly so bear with me. I have one handler, `app.use('/', express.static(__dirname + '/public'));` I have one HTML page as `/public/index.html` and that page links to `/public/style.css`. Both pages are served up just fine using the handler as shown. But I thought to myself, "Why am I using a .use(), which supports all HTTP methods (GET, POST, HEAD, etc.), when I should only be handling GET. I'll just switch .use to .get and everything should work fine." Except, it doesn't, style.css 404s. Why? Thanks. – PeterT Nov 27 '14 at 04:31
  • Updated my question with code. – PeterT Nov 27 '14 at 04:37
  • @jfriend00 Thanks for your time, I found the answer. Get is a specific endpoint, use is anything under that endpoint, as explained here... http://stackoverflow.com/questions/15601703/difference-between-app-use-and-app-get-in-express-js – PeterT Nov 27 '14 at 04:49

2 Answers2

6

app.get('/', handler) is "add / to routing table, and when http GET request arrives call handler"

app.use(middlevare) is "add middlevare to the stack".

"middleware" is a function which accepts (request, response, next), next middleware is explicitly called by previous one with next()

express.static() returns middleware - specifically, a function that checks path of request and streams content of a corresponding file to response. If you add it using app.get('/') it's never called for non-"/" routes

Andrey Sidorov
  • 24,905
  • 4
  • 62
  • 75
  • 1
    Got it. I thought .use and .get only differed by the method they respond to, but it is much deeper, esp. regarding how the endpoint is resolved. As answered here: http://stackoverflow.com/questions/15601703/difference-between-app-use-and-app-get-in-express-js – PeterT Nov 27 '14 at 04:50
2

The short answer is app.use('/', express.static(__dirname + '/public')) will match any path that begins with /. This means that anything like/about and /contact are included. However, app.get('/', express.static(__dirname + '/public')) will match only the specific route /. So, /about and /contact, for example, won't be included.

M.Z.
  • 424
  • 5
  • 12