LRU缓存在Next.js中用于速率限制时,“cache token”应该是什么?

huangapple go评论65阅读模式
英文:

What should "cache token" be when using LRU cache in Next.js for rate limiting?

问题

I am following the Next.js rate limiting example at API Routes Rate Limiting Example, and it shows this as the base module:

import type { NextApiResponse } from 'next'
import LRU from 'lru-cache'

type Options = {
  uniqueTokenPerInterval?: number
  interval?: number
}

export default function rateLimit(options?: Options) {
  const tokenCache = new LRU({
    max: options?.uniqueTokenPerInterval || 500,
    ttl: options?.interval || 60000,
  })

  return {
    check: (res: NextApiResponse, limit: number, token: string) =>
      new Promise<void>((resolve, reject) => {
        const tokenCount = (tokenCache.get(token) as number[]) || [0]
        if (tokenCount[0] === 0) {
          tokenCache.set(token, tokenCount)
        }
        tokenCount[0] += 1

        const currentUsage = tokenCount[0]
        const isRateLimited = currentUsage >= limit
        res.setHeader('X-RateLimit-Limit', limit)
        res.setHeader(
          'X-RateLimit-Remaining',
          isRateLimited ? 0 : limit - currentUsage
        )

        return isRateLimited ? reject() : resolve()
      }),
  }
}

And then its usage as:

import type { NextApiRequest, NextApiResponse } from 'next'
import { v4 as uuidv4 } from 'uuid'
import rateLimit from '../../utils/rate-limit'

const limiter = rateLimit({
  interval: 60 * 1000, // 60 seconds
  uniqueTokenPerInterval: 500, // Max 500 users per second
})

export default async function handler(
  _req: NextApiRequest,
  res: NextApiResponse
) {
  try {
    await limiter.check(res, 10, 'CACHE_TOKEN') // 10 requests per minute
    res.status(200).json({ id: uuidv4() })
  } catch {
    res.status(429).json({ error: 'Rate limit exceeded' })
  }
}

What is that CACHE_TOKEN supposed to be? In my case, I want to rate limit individual users somehow, and also rate limit globally so there's an overall limit on the traffic, in the Next.js app. My app also doesn't have user accounts; it is just a free public API which I would like to rate limit to some degree. How can I accomplish that? What technique is appropriate here?

I am currently imagining a solution where we use server-side cookies and set the cookie to a random cuid generated using a hidden secret as randomizing input. But I'm not sure where to go from that thought and what solution is most appropriate. I don't need to know the code for implementing session or cookie management; I can figure that out once I know generally the approach, so I am just looking for the high level approach to solving this problem.

Note: I am trying to ideally implement some sort of primitive rate-limiting without user accounts and without a database. It doesn't need to be perfect, but I am wondering what the standard or ideal approach is in this situation.

英文:

I am following the Next.js rate limiting example at API Routes Rate Limiting Example, and it shows this as the base module:

import type { NextApiResponse } from 'next'
import LRU from 'lru-cache'

type Options = {
  uniqueTokenPerInterval?: number
  interval?: number
}

export default function rateLimit(options?: Options) {
  const tokenCache = new LRU({
    max: options?.uniqueTokenPerInterval || 500,
    ttl: options?.interval || 60000,
  })

  return {
    check: (res: NextApiResponse, limit: number, token: string) =>
      new Promise<void>((resolve, reject) => {
        const tokenCount = (tokenCache.get(token) as number[]) || [0]
        if (tokenCount[0] === 0) {
          tokenCache.set(token, tokenCount)
        }
        tokenCount[0] += 1

        const currentUsage = tokenCount[0]
        const isRateLimited = currentUsage >= limit
        res.setHeader('X-RateLimit-Limit', limit)
        res.setHeader(
          'X-RateLimit-Remaining',
          isRateLimited ? 0 : limit - currentUsage
        )

        return isRateLimited ? reject() : resolve()
      }),
  }
}

And then its usage as:

import type { NextApiRequest, NextApiResponse } from 'next'
import { v4 as uuidv4 } from 'uuid'
import rateLimit from '../../utils/rate-limit'

const limiter = rateLimit({
  interval: 60 * 1000, // 60 seconds
  uniqueTokenPerInterval: 500, // Max 500 users per second
})

export default async function handler(
  _req: NextApiRequest,
  res: NextApiResponse
) {
  try {
    await limiter.check(res, 10, 'CACHE_TOKEN') // 10 requests per minute
    res.status(200).json({ id: uuidv4() })
  } catch {
    res.status(429).json({ error: 'Rate limit exceeded' })
  }
}

What is that CACHE_TOKEN supposed to be? In my case, I want to rate limit individual users somehow, and also rate limit globally so there's an overall limit on the traffic, in the Next.js app. My app also doesn't have user accounts; it is just a free public API which I would like to rate limit to some degree. How can I accomplish that? What technique is appropriate here?

I am currently imagining a solution where we use server-side cookies and set the cookie to a random cuid generated using a hidden secret as randomizing input. But I'm not sure where to go from that thought and what solution is most appropriate. I don't need to know the code for implementing session or cookie management; I can figure that out once I know generally the approach, so I am just looking for the high level approach to solving this problem.

Note: I am trying to ideally implement some sort of primitive rate-limiting without user accounts and without a database. It doesn't need to be perfect, but I am wondering what the standard or ideal approach is in this situation.

答案1

得分: 1

以下是翻译好的部分:

  • The cache token is the string you want to rate limit on.
  • Use the userID or authentication token/cookie.
  • Use a static string.
  • How can I accomplish that? What technique is appropriate here?
  • IP address-based would be good.
英文:

The cache token is the string you want to rate limit on.

> I want to rate limit individual users

Use the userID or authentication token/cookie.

> rate limit globally so there's an overall limit on the traffic

Use a static string.

> How can I accomplish that? What technique is appropriate here?

IP address-based would be good.

huangapple
  • 本文由 发表于 2023年4月11日 08:58:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75981715.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定