@canmertinyo/rate-limiter-mongo
Version:
A simple rate-limiting middleware for Express.js with support for in-memory, Redis, and MongoDB storage
183 lines (145 loc) • 7.05 kB
Markdown
# Express Rate Limiter
### This set of packages provides flexible and highly customizable rate-limiting solutions for Node.js applications. The core package, @canmertinyo/rate-limiter-core, includes the in-memory implementation. To enable storage-backed rate limiting, you can integrate it with either @canmertinyo/rate-limiter-mongo for MongoDB, @canmertinyo/rate-limiter-redis for Redis, or @canmertinyo/rate-limiter-memcached for Memcached.
## Rate Limiter Options
| **Option** | **Type** | **Description** | **Default Value** | **Example** |
| ------------------ | ---------- | ----------------------------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------- |
| `ms` | `number` | Time window in milliseconds for rate limiting. | `60000` (1 minute) | `ms: 60000` |
| `maxRequest` | `number` | Maximum requests allowed within the time window. | `10` | `maxRequest: 10` |
| `storage` | `object` | Storage manager for rate limits (e.g., in-memory, MongoDB, Redis, Memcached). | `undefined` (in-memory) | `storage: mongoStorage` |
| `message` | `string` | Custom message returned when rate limit is exceeded. | `"Too many requests"` | `message: "Too many requests, please try again later."` |
| `statusCode` | `number` | HTTP status code for rate limit responses. | `429` | `statusCode: 429` |
| `keyGenerator` | `function` | Function to generate a unique key for rate limiting (e.g., based on `req.ip` or headers). | `(req) => req.ip` | `keyGenerator: (req) => req.ip` |
| `skip` | `function` | Function to bypass rate limiting for certain requests (e.g., based on user role). | `undefined` | `skip: (req) => req.headers["x-user-role"] === "admin"` |
| `errorHandler` | `function` | Error handling function for issues from the storage layer. | Logs error and proceeds. | `errorHandler: (req, res, next) => next()` |
| `passOnStoreError` | `boolean` | Whether to allow requests to pass even if the storage fails. | `false` | `passOnStoreError: true` |
To install (Core version only in memory):
```bash
npm install @canmertinyo/rate-limiter-core
```
To install (Mongo store):
```bash
npm install @canmertinyo/rate-limiter-mongo mongoose
```
To install (Redis store)
```bash
npm install @canmertinyo/rate-limiter-redis ioredis
```
To install (Memcached store)
```bash
npm install @canmertinyo/rate-limiter-memcached memcached
```
# Example usage :
```typescript
import express from "express";
import { rateLimiter } from "@canmertinyo/rate-limiter-core";
const app = express();
// Apply rate limiter middleware
app.use(
rateLimiter({
ms: 60000, // Time in milliseconds
maxRequest: 5, // Maximum requests allowed within the time
//DEFAULT IS IN MEMORY
})
);
app.get("/", (req, res) => {
res.send("Welcome to the API!");
});
app.listen(3000, () => {
console.log("Server is running on http://localhost:3000");
});
```
# Using Redis As A Store Manager
```typescript
import express from "express";
import { RedisStorage } from "@canmertinyo/rate-limiter-redis";
import { rateLimiter } from "@canmertinyo/rate-limiter-core";
const app = express();
const port = 3001;
// Configure the rate limiter with Redis storage
app.use(
rateLimiter({
ms: 5000, // Time window in milliseconds
maxRequest: 2, // Maximum requests allowed in the time window
storage: new RedisStorage({ host: "127.0.0.1", port: 6379 }), // Redis configuration
})
);
// Sample route
app.get("/", (req, res) => {
res.send("Hello World!");
});
// Start the server
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
```
# Using Mongo As A Store Manager
```typescript
import express from "express";
import { MongoStorage } from "@canmertinyo/rate-limiter-mongo";
import { rateLimiter } from "@canmertinyo/rate-limiter-core";
const app = express();
const port = 3001;
// MongoDB connection string (replace with your MongoDB URL)
const mongoUrl = "mongodb://your-mongodb-url";
app.use(
rateLimiter({
ms: 5000, // Time window in milliseconds
maxRequest: 2, // Maximum requests allowed in the time window
storage: new MongoStorage(mongoUrl), // MongoDB configuration
})
);
// Sample route
app.get("/", (req, res) => {
res.send("Hello World!");
});
// Start the server
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
```
```typescript
app.use(
rateLimiter({
ms: 60000, // Time window in milliseconds
maxRequest: 10, // Maximum requests allowed
storage: mongoStorage, // Use MongoDB or Redis as storage or just leave it as empty. it will behave in memory storage
message: "Too many requests, please try again later.", // Custom rate limit message
statusCode: 429, // OPTIONAL: You can fully optimize HTTP status code for rate limit response
keyGenerator: (req) => req.ip, //OPTIONAL : Custom key generator
skip: (req) => {
//OPTIONAL :
const userRole = req.headers["x-user-role"]; // Assume user role is passed in headers
return userRole === "admin"; // Skip rate limiting for admin users
},
errorHandler: (req, res, next) => {
console.error("Rate limiter error");
next();
}, // Handle errors from storage
passOnStoreError: true, // Pass requests even if storage fails
})
);
```
# Using memcached as a store manager
```typescript
import express from "express";
import { MemcachedStore } from "@canmertinyo/rate-limiter-memcached";
import { rateLimiter } from "@canmertinyo/rate-limiter-core";
const app = express();
const port = 3001;
// Configure the rate limiter with Memcached storage
app.use(
rateLimiter({
ms: 5000, // Time window in milliseconds
maxRequest: 2, // Maximum requests allowed in the time window
storage: new MemcachedStore("127.0.0.1:11211", { //optons for customize db behaivor }), // Memcached configuration
})
);
// Sample route
app.get("/", (req, res) => {
res.send("Hello World!");
});
// Start the server
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
```