@perseidesjs/medusa-plugin-rate-limit
TypeScript icon, indicating that this package has built-in type declarations

1.0.8 • Public • Published

Perseides logo

@perseidesjs/medusa-plugin-rate-limit

npm version Tests GitHub license

A simple rate-limitting plugin for Medusa.

Purpose

This plugin was mainly built to protect your MedusaJS application from abuse. This plugin allows you to easily manage request limits without stepping outside the familiar Medusa environment.

Why Rate Limiting Matters

  1. Shield Against Attacks: Prevent Denial of Service (DoS) attempts by capping the number of requests from a single source.
  2. Boost Security: Thwart brute force attacks and other automated threats by controlling request frequency.
  3. Easy Setup: Seamlessly integrate rate limiting into your existing Medusa configuration files.

Installation

npm 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 redis_url option to the medusa-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:

const 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:

const 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 Number 5 The number of requests allowed in the given time window
window Number 60 The time window in seconds

How to use

If you want to start restricting certain routes, you can resolve the RateLimitService from the Medusa container, and then create middleware as shown below :

// src/middlewares/rate-limit.ts

import { 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 container
		const rateLimitService = req.scope.resolve<RateLimitService>('rateLimitService')


    // 2️⃣ We create a key for the current request based on the IP address for example
		const key = req.ip 
		const 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 message
		if (!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 example
		const 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 src/api/middlewares.ts file as follows:

import { 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 route
			matcher: '/store/auth',
			middlewares: [rateLimit],
		},
	],
}

Default Middleware

We also provide a out of the box middleware that you can use immediately without needing to create your own. This middleware is exposed and can be used as follows:

import { MiddlewaresConfig } from '@medusajs/medusa'
import { rateLimitRoutes } from '@perseidesjs/medusa-plugin-rate-limit'

export const config: MiddlewaresConfig = {
	routes: [
		{
			// This will limit the number of requests to 5 per 60 seconds on the auth route using the default middleware
			matcher: '/store/auth',
			middlewares: [rateLimitRoutes],
		},
	],
}

More information

You can find the 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

Package Sidebar

Install

npm i @perseidesjs/medusa-plugin-rate-limit

Weekly Downloads

25

Version

1.0.8

License

MIT

Unpacked Size

21.9 kB

Total Files

11

Last publish

Collaborators

  • adevinwild