UNPKG

cds-rate-limit

Version:

enabled rate limit pattern for CAP NodeJS Runtime

168 lines (131 loc) 4.58 kB
# CDS Rate Limit > apply `rate limit` pattern to CAP nodejs application [![npm](https://img.shields.io/npm/v/cds-rate-limit)](https://www.npmjs.com/package/cds-rate-limit) [![node-test](https://github.com/Soontao/cds-rate-limit/actions/workflows/nodejs.yml/badge.svg)](https://github.com/Soontao/cds-rate-limit/actions/workflows/nodejs.yml) [![codecov](https://codecov.io/gh/Soontao/cds-rate-limit/branch/main/graph/badge.svg?token=xzBkWloYNR)](https://codecov.io/gh/Soontao/cds-rate-limit) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Soontao_cds-rate-limit&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Soontao_cds-rate-limit) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=Soontao_cds-rate-limit&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=Soontao_cds-rate-limit) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=Soontao_cds-rate-limit&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=Soontao_cds-rate-limit) ## Get Started `package.json` ```json { "cds": { "plugins": ["cds-rate-limit"] } } ``` `cds definition` ```groovy using {cuid, managed} from '@sap/cds/common'; @path : '/sample3' service Sample3Service { // define rate limit for entity CRUD events and actions // accepts 1000 requests in 120 seconds // other requests will be rejected by HTTP 429 status @cds.rate.limit : { duration : 120, points : 1000, } entity People : cuid, managed { Name : String(255); Age : Integer; } // share global quota entity Other: cuid, managed { Name : String(255); } } ``` ## Headers - `Retry-After` - reset after seconds later - `X-RateLimit-Reset` - reset timestamp (unix timestamp) - `X-RateLimit-Limit` - total quota for each window - `X-RateLimit-Remaining` - remaining quota for current window ## RateLimiter Hierarchy > the `RateLimiter` configuration will apply restriction by order, if you do not annotate `@cds.rate.limit` on entity/action/function level, it will share the quota of the global `RateLimiter` 1. Event/Action/Function 2. Entity 3. Service 4. Global ## Options - `keyParts`: use to generated the key - `remote_ip` - req.\_.req.ip - please ref [express document](http://expressjs.com/en/guide/behind-proxies.html) to setup `trust proxy` - `user_id` - ctx.user.id - `tenant` - ctx.tenant - `points`: quota for each key (user, ip, tenant or combined) - `duration`: quota for each key in duration (reset duration for quota) ### Default Global Options **if there is no annotation on CDS Service/Entity/Action/Function, it will use the global configuration** ```js { impl: "memory", // use in-memory keyParts: ["tenant"], // generate key from tenant keyPrefix: GLOBAL_RATE_LIMITER_PREFIX, // default prefix duration: 60, // 60 seconds points: 200 * 60, // 200 requests per seconds // for anonymous requests (without authorization header) anonymous: { // per seconds per remote ip allow 1000 requests keyPrefix: GLOBAL_ANONYMOUS_RATE_LIMITER_PREFIX, duration: 10, points: 10 * 100, }, } ``` ### Example - Memory > configuration global default configuration, each user could call API 6000 times in 1 minute duration ```json { "cds": { "plugins": ["cds-rate-limit"], "config": { "rateLimit": { "impl": "memory", "duration": 60, "points": 6000, "keyParts": ["user_id"] } } } } ``` ### Example - Redis > each user in each tenant could use the API 300 times in 5 seconds duration ```json { "cds": { "plugins": [ "cds-rate-limit" ], "config": { "rateLimit": { "impl": "redis", "duration": 5, "points": 300, "keyParts": ["tenant", "user_id"], "redisOptions": { "enableOfflineQueue": false } } } } } ``` - for redis connection options, please check [ioredis document](https://www.npmjs.com/package/ioredis) or [RedisOptions type](https://github.com/luin/ioredis/blob/6f1ab9f/lib/redis/RedisOptions.ts#L188) ## Features - [x] Global Rate Limit - [x] Event Rate Limit - [x] Inner event ignore - [x] Anonymous Request Rate Limit - [x] Custom key - [ ] Global Env Configuration - [x] Redis store - [ ] Dynamic quota configuration - [ ] Sampling store to reduce remote store network consumption ## ToDo - [x] How to process anonymous requests - [ ] Documents for microservice - [ ] Performance ## [CHANGELOG](./CHANGELOG.md) ## [LICENSE](./LICENSE)