upstash / ratelimit-js

Rate limiting library for serverless runtimes
https://ratelimit-with-upstash.vercel.app/
MIT License
1.72k stars 33 forks source link

Add Deny List Feature & Add Reasons to `limit` Response #109

Closed CahidArda closed 5 months ago

CahidArda commented 5 months ago

Deny List

In redis, we keep sets of denied values. One set each for identifiers, ips, countries and user agents. Finally, there is a set of all blocked values. Upstash console is responsible for managing these sets. Ratelimit sdk is only interested in the set of all blocked values stored in key <prefix>:denyList:all.

Enabling deny list in the sdk:

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "10 s"),
  enableProtection: true // set to true
});

Passing ip, user agent or country in limit:

ratelimit.limit(
  "identifier",
  {
    ip: "12.32.12.32",
    userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
    country: "Germany"
  }
)

all three fields are optional. One can pass none/some/all.

Inside limit, we check if any of the three fields or the identifier is in the deny list. If so, we return {success: false, reason: "denyList", ...}

Deny List Cache

When a value is found in the deny list at redis, we store the value for a minute in a local cache. If that value is passed to the limit method in the next minute, we block the request with reason: "denyList" without making any requests to Redis.

reason field in limit response

We add a new field to the response of limit, which can be either "timeout", "cacheBlock" or "denyList". In the case of "denyList", there is an additional field _deniedValue which denotes the value in deny list.

Deny List Analytics

When a request is denied, we submit increment {identifier: <deniedValue>, success:"denied"} by one.

Previously:

Todo:

linear[bot] commented 5 months ago

DX-960 Ratelimit - Deny List Update

vercel[bot] commented 5 months ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
ratelimit-with-vercel-kv ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 31, 2024 10:14am
CahidArda commented 5 months ago

I think we can go ahead with this PR even though the tests are not passing because they are flaky. Here are two runs with two different tests failing even though the code didn't change between them: 1, 2.

I looked into recording network traffic like langchain does but that's only in python. I want to fix the tests but let's do it another time