[node.js] Difference between app.use and app.get in express.js

I'm kind of new to express and node.js, and I can't figure out the difference between app.use and app.get. It seems like you can use both of them to send information. For example:

app.use('/',function(req, res,next) {
    res.send('Hello');
    next();
});

seems to be the same as this:

app.get('/', function (req,res) {
   res.send('Hello');
});

This question is related to node.js express

The answer is


Simply app.use means “Run this on ALL requests”
app.get means “Run this on a GET request, for the given URL”


app.use is the "lower level" method from Connect, the middleware framework that Express depends on.

Here's my guideline:

  • Use app.get if you want to expose a GET method.
  • Use app.use if you want to add some middleware (a handler for the HTTP request before it arrives to the routes you've set up in Express), or if you'd like to make your routes modular (for example, expose a set of routes from an npm module that other web applications could use).

app.get is called when the HTTP method is set to GET, whereas app.use is called regardless of the HTTP method, and therefore defines a layer which is on top of all the other RESTful types which the express packages gives you access to.


There are 3 main differences I have found till now. The 3rd one is not so obvious and you may find it interesting. The differences are the same for the express router. That means router.use() and router.get() or other post, put, all, etc methods has also same difference.

1

  • app.use(path, callback) will respond to any HTTP request.
  • app.get(path, callback) will only respond to GET HTTP request. In the same way, post, put, etc will respond to their corresponding request. app.all() responds to any HTTP request so app.use() and app.all() are the same in this part.

2

  • app.use(path, callback) will match the prefix of the request path and responds if any prefix of the request path matches the path parameter. Such as if the path parameter is "/", then it will match "/", "/about", "/users/123" etc.
  • app.get(path, callback) Here get will match the whole path. Same for other HTTP requests and app.all(). Such as, if the path parameter is "/", then it will only match "/".

3

next('route') doesn't work on the middleware/callback functions of app.use(). It works only on app.get(), app.all() and other similar function of other HTTP requests.

According to express documentation:

next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.

METHOD is the HTTP method of the request that the middleware function handles (such as GET, PUT, or POST) in lowercase.

From here we will use the keyword METHOD instead of get, post, all, etc.
But what is next('route')?!

Let's see.

next('route')

we see, app.use() or app.METHOD() can take several callback/middleware functions.

From the express documentation:

Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.

If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.

So we see each middleware functions have to either call the next middleware function or end the response. And this is same for app.use() and app.METHOD().

But sometimes in some conditions, you may want to skip all the next callback functions for the current route but also don't want to end the response right now. Because maybe there are other routes which should be matched. So to skip all the callback functions of the current route without ending the response, you can run next('route'). It will skip all the callback functions of the current route and search to match the next routes.

For Example (From express documentation):

app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // send a regular response
  res.send('regular')
})

// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
  res.send('special')
})

See, here in a certain condition(req.params.id === '0') we want to skip the next callback function but also don't want to end the response because there is another route of the same path parameter which will be matched and that route will send a special response. (Yeah, it is valid to use the same path parameter for the same METHOD several times. In such cases, all the routes will be matched until the response ends). So in such cases, we run the next('route') and all the callback function of the current route is skipped. Here if the condition is not met then we call the next callback function.

This next('route') behavior is only possible in the app.METHOD() functions.

Recalling from express documentation:

next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.

Since skipping all callback functions of the current route is not possible in app.use(), we should be careful here. We should only use the middleware functions in app.use() which need not be skipped in any condition. Because we either have to end the response or traverse all the callback functions from beginning to end, we can not skip them at all.

You may visit here for more information


Difference between app.use & app.get:

app.use ? It is generally used for introducing middlewares in your application and can handle all type of HTTP requests.

app.get ? It is only for handling GET HTTP requests.

Now, there is a confusion between app.use & app.all. No doubt, there is one thing common in them, that both can handle all kind of HTTP requests. But there are some differences which recommend us to use app.use for middlewares and app.all for route handling.

  1. app.use() ? It takes only one callback.
    app.all() ? It can take multiple callbacks.

  2. app.use() will only see whether url starts with specified path.
    But, app.all() will match the complete path.

For example,

app.use( "/book" , middleware);
// will match /book
// will match /book/author
// will match /book/subject

app.all( "/book" , handler);
// will match /book
// won't match /book/author   
// won't match /book/subject    

app.all( "/book/*" , handler);
// won't match /book        
// will match /book/author
// will match /book/subject
  1. next() call inside the app.use() will call either the next middleware or any route handler, but next() call inside app.all() will invoke the next route handler (app.all(), app.get/post/put... etc.) only. If there is any middleware after, it will be skipped. So, it is advisable to put all the middlewares always above the route handlers.

In addition to the above explanations, what I experience:

app.use('/book', handler);  

will match all requests beginning with '/book' as URL. so it also matches '/book/1' or '/book/2'

app.get('/book')  

matches only GET request with exact match. It will not handle URLs like '/book/1' or '/book/2'

So, if you want a global handler that handles all of your routes, then app.use('/') is the option. app.get('/') will handle only the root URL.


Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`

Examples related to express

UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block jwt check if token expired Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] npm notice created a lockfile as package-lock.json. You should commit this file Make Axios send cookies in its requests automatically What does body-parser do with express? SyntaxError: Unexpected token function - Async Await Nodejs Route.get() requires callback functions but got a "object Undefined" How to redirect to another page in node.js