Help middleware with express-rate-limit
Answered
Alex.Mazaltov Developer๛ posted this in #help-forum
i want to apply rateLimiter middleware in file:
I'm stuck with on the following state:
I understand that there may be better way to limit amount of requests to openai that will be possible to perform for visitors.
To prevent token spending
middleware/rateLimiter.ts to my main middleware.ts file inside root folder for NEXT 14 app taken from vercel template. [See my latest commits](https://github.com/alexmazaltov/ai-chatbot/commits/main/)I'm stuck with on the following state:
middleware/rateLimiter.ts
import rateLimit from 'express-rate-limit';
import { kv } from '@vercel/kv';
import { getSession } from 'next-auth/react';
const createRateLimiter = (limit: number, windowMs: number) => {
return rateLimit({
windowMs,
max: limit,
standardHeaders: true,
legacyHeaders: false,
keyGenerator: async (req, res) => {
const session = await getSession({ req: req as any});
const ip = req.ip;
return session?.user?.id ? `user:${session.user.id}` : `ip:${ip}`;
},
store: {
async increment(key) {
const count = await kv.incr(key);
await kv.expire(key, windowMs / 1000);
return { totalHits: count, resetTime: Date.now() + windowMs };
},
async decrement(key) {
return kv.decr(key);
},
async resetKey(key) {
return kv.del(key);
}
}
});
};
export const rateLimiter = async (req, res, next) => {
try {
const session = await getSession({ req: req as any });
const limit = session?.user ? 30 : 10;
const windowMs = 24 * 60 * 60 * 1000; // 24 hours
const limiter = createRateLimiter(limit, windowMs);
return limiter(req, res, next);
} catch (error) {
next(error);
}
};I understand that there may be better way to limit amount of requests to openai that will be possible to perform for visitors.
To prevent token spending
Answered by Texas leafcutting ant
but this solution is not designed to be used as middleware.
You can adjust
You can adjust
lib/chat/actions.tsxdiff --git a/lib/chat/actions.tsx b/lib/chat/actions.tsx
index ca6de3d..e4c41cb 100644
--- a/lib/chat/actions.tsx
+++ b/lib/chat/actions.tsx
@@ -35,6 +35,17 @@ import { saveChat } from '@/app/actions'
import { SpinnerMessage, UserMessage } from '@/components/stocks/message'
import { Chat, Message } from '@/lib/types'
import { auth } from '@/auth'
+import { RateLimiterMemory } from 'rate-limiter-flexible'
+
+const rateLimiterUnauthenticated = new RateLimiterMemory({
+ points: 3, // 3 requests
+ duration: 3600, // per hour
+});
+
+const rateLimiterAuthenticated = new RateLimiterMemory({
+ points: 6, // 6 requests
+ duration: 3600, // per hour
+});
async function confirmPurchase(symbol: string, price: number, amount: number) {
'use server'
@@ -109,6 +120,20 @@ async function confirmPurchase(symbol: string, price: number, amount: number) {
async function submitUserMessage(content: string) {
'use server'
+ const session = await auth()
+ const isAuthenticated = session && session.user
+
+ try {
+ if (isAuthenticated && session && session.user) {
+ await rateLimiterAuthenticated.consume(session.user.id)
+ } else {
+ await rateLimiterUnauthenticated.consume('unauthenticated')
+ }
+ } catch (rateLimiterRes) {
+ // Handle rate limit exceeded
+ throw new Error('Rate limit exceeded. Please try again later.')
+ }
+
const aiState = getMutableAIState<typeof AI>()
aiState.update({4 Replies
middleware.ts
import { rateLimiter } from './middleware/rateLimiter';
import NextAuth from 'next-auth';
import { authConfig } from './auth.config';
import { NextApiHandler } from 'next';
export default async function middleware(req, res, next: NextApiHandler) {
await rateLimiter(req, res, async () => {
await NextAuth(authConfig).auth(req, res, next);
});
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)']
};Any suggestions how to properly implement such middleware?
Texas leafcutting ant
instead of using express-rate-limit use the
rate-limiter-flexibleTexas leafcutting ant
but this solution is not designed to be used as middleware.
You can adjust
You can adjust
lib/chat/actions.tsxdiff --git a/lib/chat/actions.tsx b/lib/chat/actions.tsx
index ca6de3d..e4c41cb 100644
--- a/lib/chat/actions.tsx
+++ b/lib/chat/actions.tsx
@@ -35,6 +35,17 @@ import { saveChat } from '@/app/actions'
import { SpinnerMessage, UserMessage } from '@/components/stocks/message'
import { Chat, Message } from '@/lib/types'
import { auth } from '@/auth'
+import { RateLimiterMemory } from 'rate-limiter-flexible'
+
+const rateLimiterUnauthenticated = new RateLimiterMemory({
+ points: 3, // 3 requests
+ duration: 3600, // per hour
+});
+
+const rateLimiterAuthenticated = new RateLimiterMemory({
+ points: 6, // 6 requests
+ duration: 3600, // per hour
+});
async function confirmPurchase(symbol: string, price: number, amount: number) {
'use server'
@@ -109,6 +120,20 @@ async function confirmPurchase(symbol: string, price: number, amount: number) {
async function submitUserMessage(content: string) {
'use server'
+ const session = await auth()
+ const isAuthenticated = session && session.user
+
+ try {
+ if (isAuthenticated && session && session.user) {
+ await rateLimiterAuthenticated.consume(session.user.id)
+ } else {
+ await rateLimiterUnauthenticated.consume('unauthenticated')
+ }
+ } catch (rateLimiterRes) {
+ // Handle rate limit exceeded
+ throw new Error('Rate limit exceeded. Please try again later.')
+ }
+
const aiState = getMutableAIState<typeof AI>()
aiState.update({Answer