Skip to content
Advertisement

NodeJS middleware calling order

Why res.send("main page 2") not overriding res.send("main page 1") when I request localhost:3000 ?
While execucing this code in NodeJS only console.log("midddleware") is calling from app.use method but not res.send. I wonder why it works like that.

const express = require('express')
const app = express()

app.get('/', function(req, res){
    res.send("main page 1")
})

app.use("/", function(req, res) {
    res.send("main page 2")
    console.log("midddleware")
})

app.listen(3000)

Answer

You are likely being tricked by the second request (for the favicon.ico) that the browser sends to your server.

Examining your code in more detail, here’s what it will do:

const express = require('express')
const app = express()

app.get('/', function(req, res){
    res.send("main page 1")
})

app.use("/", function(req, res) {
    res.send("main page 2")
    console.log("midddleware")
})

app.listen(3000)

If you do a GET request for / to your server, Express matches routes in the order declared so the first one that will match is the app.get(). It will send the response with res.send("main page 1") and because it does NOT call next(), all routing will be done and the app.use("/", ...) is never hit.

But, if you typed http://localhost:3000 into the browser, that is not the only request that the browser will send to your server. The browser will also send a request for http://localhost:3000/favicon.ico (the web site icon the browser likes to display).

That request will not be matched by the app.get("/", ...), but because app.use() accepts partial matches (app.get() requires full matches only), the /favicon.ico request will be matched by app.use("/", ..) and you will see your console.log("middleware"). You won’t see the results of res.send("main page 2") because when the browser requested the favicon and got back some plain text, it will just ignore that is it clearly isn’t the icon it was looking for.

If you modify your middleware to log the actual URL that is being requested, then all should be clear:

app.use("/", function(req, res) {
    res.send("main page 2")
    console.log("midddleware", req.originalUrl);    // log the actual URL
})
Advertisement