5

All:

I am new to Express 4 router.

When I tried some login/signup example, I got one question about the .use and .get/.post function:

I saw sometimes it uses:

var express = require('express');
var router = express.Router();

router.get('/hello', function(req, res, next) {
  res.send("Welcome");
});

and in main app, we use it like:

app.use("/", router);

While some other time, it uses:

var express = require('express');
var router = express.Router();

//here the router uses .use() function rather than .get/.post
router.use('/hello', function(req, res, next) {
  res.send("Welcome");
});

and in main app, we use it like:

app.use("/", router);

So I am wondering what is the difference between them, does the .use() just a general name for all of get/post/put/... together?

I find this post: Difference between app.use and app.get in express.js

But still not feel easy to understand this....

Thanks

Community
  • 1
  • 1
Kuan
  • 11,149
  • 23
  • 93
  • 201
  • Does this answer your question? [Difference between app.use and app.get in express.js](https://stackoverflow.com/questions/15601703/difference-between-app-use-and-app-get-in-express-js) – S.Nakib Oct 22 '20 at 05:53

2 Answers2

7

In addition to what Jonathan Lonowski said in the posted link, it might help to not compare use to get and post, but to compare it to all because both all and use work regardless of the HTTP verb used while that's obviously not true for get. Everything I'm about to say applies if you replace "all" with "get", it'll just narrow that handler down to a specific HTTP verb.

So, what's the difference between all and use?

app.all will handle incoming requests at the specified URL path regardless of the HTTP verb, just as app.use does. However, how it compares the requested URL to the handler is different. For example:

var r = express.Router();
r.use('/foo', function (...) { ... }); // Route A
r.all('/bar', function (...) { ... }); // Route B

If you make a request to /foo/123 Route A will be run.

If you make a request, however, to /bar/123 Route B will NOT be run.

This is because with HTTP verbs express compares the full path, but with 'use' it only cares about the beginning of the url. Because the URL /foo/123 begins with /foo Route A will run, but because /bar/123 does not match the FULL URL, Route B will not be. Note: You could make .all behave in the same way: r.all('/bar/*', ...), but use is easier and more appropriate for this.

So, what you would tend to mount with one vs the other is different. For example:

var app = express();
var router1 = express.Router();
var router2 = express.Router();

router2.all('*', function (req, res) { ... }); // Must specify a path!

router1.use('/secondary-routes', router2); // Can't do this with all.

app.use(router1); // Look Ma, no path!

Here I've used all to handle a request coming in, where I've used use to mount an entire router. Also, note that the usage of router.METHOD functions require a URL string as the first parameter, while use does not.

At the end of the day, if you:

  1. Want all requests that come in under a given path (or even every request) to use the specified middleware, or
  2. Want to mount an entire sub router/application, or
  3. Want to include a plugin into your application

... Then use is probably what you want.

If you:

  1. Are handling a specific request at a specific URL path (i.e. probably not doing a * match in the URL)
  2. Generally won't be calling next and will instead actually be handling the request

... Then an HTTP verb method (like get, post or all) is probably what you want.

Adam Terlson
  • 12,610
  • 4
  • 42
  • 63
  • Thanks. This is very helpful explaination. But one thing about the URL match: is this matching just like regex match? I do not quite sure my understanding about this, if I want .all to match /bar/xxx/ but not /bar/xxx and not /bar/xxx/yyy and so on, how do I specify that url? – Kuan May 21 '15 at 17:58
  • It *can* be a regex, but isn't always. [See this](http://expressjs.com/api.html#router.METHOD). Note the different formats a URL might take. – Adam Terlson May 21 '15 at 18:02
  • Sorry, I did not quite follow this, what should I particularly pay attention to note? – Kuan May 21 '15 at 18:05
  • Paths in express can be `/foo` or `/foo/:bar` or `/foo/:bar(\\w+\.\.\\w+)`. These are not all regex's, the URL matching in express is more complex than that. – Adam Terlson May 21 '15 at 18:08
  • To answer your first comment after edit, `router.all('/bar/xxx/')` will match no other routes and the trailing slash will be required. It will NOT handle `/bar/xxx/yyy`. – Adam Terlson May 21 '15 at 18:11
  • Another question I am wondering about next() is: when we reach next(), it means the request is gonna passed to next middleware or request handler, is that right? If so, I wonder what happen if I have some code which add attribute to req, will it report error? – Kuan May 21 '15 at 21:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/78560/discussion-between-adam-terlson-and-kuan). – Adam Terlson May 22 '15 at 17:12
1

.use is used in 2 cases, middlewares and "modular mountable route handlers".

In your example

router.use('/hello', function(req, res, next) {
  res.send("Welcome");
});

This means that any requests sent to /hello will be terminated with "Welcome" and the actual .get attached to /hello will not be called.

So, in short, call use when you need to apply some general middlewares or want to do modular architecture with routers. use can be "used" as request handlers, but you shouldn't because it is not designed for that purpose

Tan Nguyen
  • 3,354
  • 3
  • 21
  • 18
  • Thanks, Just to verify my understanding is right: so the main diff is that .use() can make a middleware which works similar to how .get/.post/... works but more general cos it will apply its request handling to all which mount to its url? – Kuan May 21 '15 at 17:52
  • As far as I know, Yes – Tan Nguyen May 21 '15 at 18:40