简体   繁体   中英

Why does my middleware function does not work if its called function is not defined in the same file?

I am facing the following problem :

Case 1 (working case) :

file middleware.ts (library for middleware utils functions)

import { NextApiRequest, NextApiResponse } from 'next'
import rateLimit from 'express-rate-limit'

export function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: Function) {
    return new Promise((resolve, reject) => {
      fn(req, res, (result: any) => {
        if (result instanceof Error) {
          return reject(result)
        }
        return resolve(result)
      })
    })
}

export const limiter = rateLimit({
    keyGenerator: function (req: any) {
        return req.headers["x-forwarded-for"] || req.connection.remoteAddress; 
    }, // Needed because of issue : https://issueexplorer.com/issue/nfriedly/express-rate-limit/254
    windowMs: 60 * 1000, // 1 minute
    max: 5, // 5 requests per IP
})

file login.ts (my API entry point)

import { NextApiRequest, NextApiResponse } from 'next'
import { limiter, runMiddleware } from '../../lib/middleware'

module.exports = async (req: NextApiRequest, res: NextApiResponse) => {


    // Run middlewares
    try {
        await runMiddleware(req, res, limiter)
    } catch {
        res.status(500)
        res.end(JSON.stringify({errorCode: 'unknown', errorValue: ''}))
        return
    }

    if (req.method === 'POST') {
        res.status(200)
        res.end(JSON.stringify({errorCode: 'ok', errorValue: ''}))
    }
}

In this case, if I try more than 5 times to reach my API, I get the message "Too many requests ..." which is what I want.

Case 2 (non-working case) :

file middleware.ts (library for middleware utils functions)

import { NextApiRequest, NextApiResponse } from 'next'

export function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: Function) {
    return new Promise((resolve, reject) => {
      fn(req, res, (result: any) => {
        if (result instanceof Error) {
          return reject(result)
        }
        return resolve(result)
      })
    })
}

file login.ts (my API entry point)

import { NextApiRequest, NextApiResponse } from 'next'
import rateLimit from 'express-rate-limit'
import { runMiddleware } from '../../lib/middleware'

// Run middlewares
    try {
        const limiter = rateLimit({
            keyGenerator: function (req: any) {
                return req.headers["x-forwarded-for"] || req.connection.remoteAddress; 
            }, // Needed because of issue : https://issueexplorer.com/issue/nfriedly/express-rate-limit/254
            windowMs: 60 * 1000, // 1 minute
            max: 5, // 5 requests per IP
        })
        await runMiddleware(req, res, limiter)
    } catch {
        res.status(500)
        res.end(JSON.stringify({errorCode: 'unknown', errorValue: ''}))
        return
    }

    if (req.method === 'POST') {
        res.status(200)
        res.end(JSON.stringify({errorCode: 'ok', errorValue: ''}))
    }

I don't see the differences between these two cases that could explain how it is not working in my second case. Does someone has an explanation ?

Thanks in advance.

The answer is given in comment by @juliomalves :

"That's because you're declaring and assigning the value to limiter on each request, rateLimit gets called every time. Try moving the limiter declaration outside the handler function."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM