@perseidesjs/medusa-plugin-rate-limit
Website|Medusa
A simple rate-limit plugin for Medusa.
Installation
1npm install @perseidesjs/medusa-plugin-rate-limit
Usage
This plugin uses Redis under the hood, this plugin will also work in a development environment thanks to the fake Redis instance created by Medusa, remember to use Redis in production, by just passing the Copy to clipboard
redis_url
option to the Copy to clipboardmedusa-config.js > projectConfig
object.
Plugin configuration
You need to add the plugin to your Medusa configuration before you can use the rate limitting service. To do this, import the plugin as follows:
12345const plugins = [`medusa-fulfillment-manual`,`medusa-payment-manual`,`@perseidesjs/medusa-plugin-rate-limit`,]
You can also override the default configuration by passing an object to the plugin as follows:
123456789101112const plugins = [`medusa-fulfillment-manual`,`medusa-payment-manual`,{resolve: `@perseidesjs/medusa-plugin-rate-limit`,/** @type {import('@perseidesjs/medusa-plugin-rate-limit').PluginOptions} */options: {limit: 5,window: 60,},},]
Default configuration
Option | Type | Default | Description |
---|---|---|---|
limit | Copy to clipboardNumber | Copy to clipboard5 | The number of requests allowed in the given time window |
window | Copy to clipboardNumber | Copy to clipboard60 | The time window in seconds |
How to use
If you want to start restricting certain routes, you can resolve the Copy to clipboard
RateLimitService
from the Medusa container, and then create middleware as shown below :
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748// src/middlewares/rate-limit.tsimport { type MedusaRequest, type MedusaResponse } from '@medusajs/medusa'import type { NextFunction } from 'express'import type { RateLimitService } from '@perseidesjs/medusa-plugin-rate-limit'/*** A simple rate limiter middleware based on the RateLimitService* @param limit {number} - Number of requests allowed per window* @param window {number} - Number of seconds to wait before allowing requests again* @returns*/export default async function rateLimit(req: MedusaRequest,res: MedusaResponse,next: NextFunction,) {try {// 1️⃣ We resolve the RateLimitService from the containerconst rateLimitService = req.scope.resolve<RateLimitService>('rateLimitService')// 2️⃣ We create a key for the current request based on the IP address for exampleconst key = req.ipconst rateLimitKey = `rate_limit:${key}`const allowed = await rateLimitService.limit(rateLimitKey)// 3️⃣ If the request is not allowed, we return a 429 status code and a JSON response with an error messageif (!allowed) {const retryAfter = await rateLimitService.ttl(rateLimitKey)res.set('Retry-After', String(retryAfter))res.status(429).json({ error: 'Too many requests, please try again later.' })return}// 4️⃣ Otherwise, we can continue, below I'm getting the remaining attempts for the current key for exampleconst remaining = await rateLimitService.getRemainingAttempts(rateLimitKey)res.set('X-RateLimit-Limit', String(rateLimitService.getOptions().limit))res.set('X-RateLimit-Remaining', String(remaining))next()} catch (error) {next(error)}}
And then use it in your Copy to clipboard
src/api/middlewares.ts
file as follows:123456789101112import { MiddlewaresConfig } from '@medusajs/medusa'import rateLimit from './middlewares/rate-limit'export const config: MiddlewaresConfig = {routes: [{// This will limit the number of requests to 5 per 60 seconds on the auth routematcher: '/store/auth',middlewares: [rateLimit],},],}
More information
You can find the Copy to clipboard
RateLimitService
class in the src/services/rate-limit.ts file.License
This project is licensed under the MIT License - see the LICENSE file for details