1

I've been trying to add rate limiter to my APIs on Nuxt 3 but I can't seem to figure it out. I am using the express-rate-limit module.

In my middleware. /server/middleware/rate-limiter.ts

import rateLimit from 'express-rate-limit'

const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes)
    message: 'Too many accounts created from this IP, please try again after an hour'
})

export default defineEventHandler(async (event) => {
    await limiter(event)
})

With that set up in the middleware, I am expecting a X-RateLimit-Limit and X-RateLimit-Remaining in the header. When I test the API on Postman, I don't see the expected headers added in the header. It should be something like this.
enter image description here

This is the error I got on the console.

[request error] [unhandled] [500] next is not a function 

Anyone experiencing this issue as well? Thanks!

Silver
  • 71
  • 6

1 Answers1

1

You are getting the this error it is because you need to specify the next inside the limiter

In your middleware, you should use the fromNodeMiddleware

~/server/middleware/rate-limiter.ts

import rateLimit from 'express-rate-limit'

const limiter = rateLimit({
    windowMs: 60 * 60 * 1000, // 1 hour
    max: 5, // Limit each IP to 5 create account requests per `window` (here, per hour)
    message: 'Too many accounts created from this IP, please try again after an hour',
    keyGenerator: function (req) {
        return req.headers['x-forwarded-for'] || req.connection.remoteAddress
    }
})

export default fromNodeMiddleware(async (req, res, next) => {
    limiter(req, res, next)
    next()
})

When you test the API on Postman, you should be able to see the rate limit headers enter image description here

The Problem ‼️

When you lower the max to 5 to test if the API message of the limiter works. You'll get an error, like this.

[unhandledRejection] TypeError: response.status is not a function

That is because the response.status does not exist on Nuxt and this module is for express.

✅ Recommended

Since I think we can't use the express rate module, I would recommend using the very popular module called limiter

In your Middleware, change it to this.

import { RateLimiter } from "limiter";

const tokensPerInterval = 5
const interval = 15 * 60 * 1000
const limiter = new RateLimiter(
    {
        tokensPerInterval,
        interval,
        fireImmediately: true
    });

export default fromNodeMiddleware(async (req, res, next) => {
    const remainingRequest = await limiter.removeTokens(1)
    res.setHeader('X-RateLimit-Limit', tokensPerInterval);
    res.setHeader('X-RateLimit-Remaining', remainingRequest);
    res.setHeader('X-RateLimit-Reset', interval)
    if (remainingRequest < 0) {
        res.writeHead(429, { 'Content-Type': 'text/plain;charset=UTF-8' });
        res.end('429 Too Many Requests - your IP is being rate limited');
    }
    next()
})

See screen record video https://streamable.com/4ffiv6

There is also a Nuxt module it. If you are intrested https://nuxt.com/modules/security

ReaganM
  • 1,290
  • 1
  • 11