Search code examples
javascriptnode.jsexpressmiddlewareexpress-router

Express middleware calls multiple times


I've checked other posts related to this topic and couldn't find the problem in my code.

const myMiddleware = (fn) => {
    return (req, res, next) => {
        var fullUrl = req.protocol + '://' + req.get('host') + req.url;
        console.log(fullUrl)
        next()
    }
}

const app = express()

app.use('/dist', express.static(__dirname + '/client/dist'))
app.use('/static', express.static(__dirname + '/client/static'))

app.use(bodyParser.urlencoded({ extended: false }))
app.use(cookieParserMiddleware())
app.use(passport.initialize())

const server = https.createServer(options, app)

app.get('/', myMiddleware((req, res) => {
    res.sendFile(__dirname + '/client/dist/index.html')
}))

app.all('*', (req, res) => {
    res.redirect('/')
})

server.listen(8080, function listening() {
    console.log('Listening on %d', server.address().port)
})

Without the myMiddleware on '/' path everything works as expected. With myMiddleware attached as app.get('/', myMiddleware((req, res) => { then myMiddleware is called multiple times without res.sendFile(__dirname + '/client/dist/index.html') being called.


EDIT: The bug below is fixed with jfriend00's solution. The middleware getting called multiple times still exists. The reason is favicon and some other assets are not being captured by app.use('/static', express.static(__dirname + '/client/static')) line. Fixing path solved the first bug as well

On top of that problem, I've tried removing the part below but then the app doesn't work at all. My guess is there are 2 bugs here.

app.all('*', (req, res) => {
    res.redirect('/')
})

I have posted an image on how it looks when removing app.all('*'..)

enter image description here


Solution

  • I'm going to make a guess here.

    Change this:

    app.get('/', myMiddleware((req, res) => {
        res.sendFile(__dirname + '/client/dist/index.html')
    }));
    

    to this:

    app.get('/', myMiddleware(), (req, res) => {
        res.sendFile(__dirname + '/client/dist/index.html')
    }));
    

    So that your res.sendFile() actually gets called after the myMiddleware calls next().


    Then, remove the fn argument so you have this (doesn't change execution, but removes misleading and unused argument):

    const myMiddleware = () => {
        return (req, res, next) => {
            var fullUrl = req.protocol + '://' + req.get('host') + req.url;
            console.log(fullUrl)
            next()
        }
    }