{"_id":"@chubbyts/chubbyts-undici-rate-limit","_rev":"3-d98054e4cbdc74691fb8cdfed07758db","name":"@chubbyts/chubbyts-undici-rate-limit","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@chubbyts/chubbyts-undici-rate-limit","version":"1.0.0","keywords":["chubbyts","middleware","rate-limit","rate-limiter","rate-limiter-flexible","throttle","undici"],"author":"Dominik Zogg","license":"MIT","_id":"@chubbyts/chubbyts-undici-rate-limit@1.0.0","maintainers":[{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"}],"dist":{"shasum":"b654330dbc47113780065f438390bed662804b5d","tarball":"https://registry.npmjs.org/@chubbyts/chubbyts-undici-rate-limit/-/chubbyts-undici-rate-limit-1.0.0.tgz","fileCount":9,"integrity":"sha512-IUE4nixu07ggCWVBVtu63xIT3Nj/+folv3Ss83NnsET8e1Vk84YQ2eLQhMJGKsDZZvQMN6Q1HB7JMX2due135Q==","signatures":[{"sig":"MEUCIAcvfVUzD11XtstbpLpdQdwzNTKJKSbM323p58XEj2vBAiEA9xSS0Pq+iP9UqZ5+29/GMnnz2/viJs3meJGZbky3130=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31211},"type":"module","engines":{"node":">=22"},"exports":{"./*":{"types":"./*.d.ts","import":"./*.js","default":"./*.js"}},"scripts":{"cs":"prettier --check src tests","lint":"oxlint src tests vitest.config.ts","test":"vitest","build":"rm -Rf dist && tsc","cs-fix":"prettier --write src tests","lint-fix":"oxlint --fix src tests vitest.config.ts","infection":"stryker run"},"_npmUser":{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"},"prettier":{"tabWidth":2,"printWidth":120,"singleQuote":true,"trailingComma":"all"},"repository":{"url":"chubbyts/chubbyts-undici-rate-limit","type":"git"},"description":"A minimal rate limiting middleware for chubbyts-undici-server.","directories":{},"_nodeVersion":"24.20.0","dependencies":{"rate-limiter-flexible":"^11.2.0","@chubbyts/chubbyts-dic-types":"^2.3.0","@chubbyts/chubbyts-undici-server":"^1.2.0","@chubbyts/chubbyts-dic-config-factory":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"oxlint":"^1.77.0","vitest":"^4.1.10","prettier":"^3.9.6","typescript":"^7.0.2","@types/node":"^26.1.2","@vitest/coverage-v8":"^4.1.10","@stryker-mutator/core":"^9.6.1","@chubbyts/chubbyts-oxlint":"^1.0.1","@chubbyts/chubbyts-dic-config":"^2.3.0","@stryker-mutator/vitest-runner":"^9.6.1","@chubbyts/chubbyts-function-mock":"^2.3.0"},"_npmOperationalInternal":{"tmp":"tmp/chubbyts-undici-rate-limit_1.0.0_1788088930271_0.39047602783616253","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@chubbyts/chubbyts-undici-rate-limit","version":"1.1.0","keywords":["chubbyts","middleware","rate-limit","rate-limiter","rate-limiter-flexible","throttle","undici"],"author":"Dominik Zogg","license":"MIT","_id":"@chubbyts/chubbyts-undici-rate-limit@1.1.0","maintainers":[{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"}],"dist":{"shasum":"6e61d0ec85e813bbaa7d05aa59e166d602203d6e","tarball":"https://registry.npmjs.org/@chubbyts/chubbyts-undici-rate-limit/-/chubbyts-undici-rate-limit-1.1.0.tgz","fileCount":9,"integrity":"sha512-Z+aFu9l2YfceJvqb6UTxOeL6WRJ8FsZR6aspG7Pqq6w+38j8yY3mZGiGPcpYgKS7MK8Qi9KoAKXAuRoDPy+pVg==","signatures":[{"sig":"MEQCIA6zlc5WxfvNDEyi1tJKkqnKtgBwWfAH6Zx7svvY+IlNAiBREWdnj6Qu/BIkz9CNFkkBwYmDZhIgC5WpWvXsTafI9g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":32421},"type":"module","engines":{"node":">=22"},"exports":{"./*":{"types":"./*.d.ts","import":"./*.js","default":"./*.js"}},"scripts":{"cs":"prettier --check src tests","lint":"oxlint src tests vitest.config.ts","test":"vitest","build":"rm -Rf dist && tsc","cs-fix":"prettier --write src tests","lint-fix":"oxlint --fix src tests vitest.config.ts","infection":"stryker run"},"_npmUser":{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"},"prettier":{"tabWidth":2,"printWidth":120,"singleQuote":true,"trailingComma":"all"},"repository":{"url":"chubbyts/chubbyts-undici-rate-limit","type":"git"},"description":"A minimal rate limiting middleware for chubbyts-undici-server.","directories":{},"_nodeVersion":"24.20.0","dependencies":{"rate-limiter-flexible":"^11.2.0","@chubbyts/chubbyts-dic-types":"^2.3.0","@chubbyts/chubbyts-http-error":"^3.4.1","@chubbyts/chubbyts-undici-server":"^1.2.0","@chubbyts/chubbyts-dic-config-factory":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"oxlint":"^1.77.0","vitest":"^4.1.10","prettier":"^3.9.6","typescript":"^7.0.2","@types/node":"^26.1.2","@vitest/coverage-v8":"^4.1.10","@stryker-mutator/core":"^9.6.1","@chubbyts/chubbyts-oxlint":"^1.0.1","@chubbyts/chubbyts-dic-config":"^2.3.0","@stryker-mutator/vitest-runner":"^9.6.1","@chubbyts/chubbyts-function-mock":"^2.3.0"},"_npmOperationalInternal":{"tmp":"tmp/chubbyts-undici-rate-limit_1.1.0_1788107668307_0.749841088451968","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@chubbyts/chubbyts-undici-rate-limit","type":"module","version":"1.2.0","description":"A minimal rate limiting middleware for chubbyts-undici-server.","keywords":["chubbyts","middleware","rate-limit","rate-limiter","rate-limiter-flexible","throttle","undici"],"author":"Dominik Zogg","license":"MIT","repository":{"type":"git","url":"chubbyts/chubbyts-undici-rate-limit"},"prettier":{"printWidth":120,"tabWidth":2,"singleQuote":true,"trailingComma":"all"},"exports":{"./*":{"types":"./*.d.ts","import":"./*.js","default":"./*.js"}},"engines":{"node":">=22"},"dependencies":{"@chubbyts/chubbyts-dic-config-factory":"^1.0.0","@chubbyts/chubbyts-dic-types":"^2.3.0","@chubbyts/chubbyts-http-error":"^3.5.0","@chubbyts/chubbyts-undici-server":"^1.2.0","rate-limiter-flexible":"^11.2.0"},"devDependencies":{"@chubbyts/chubbyts-dic-config":"^2.3.0","@chubbyts/chubbyts-function-mock":"^2.3.0","@chubbyts/chubbyts-oxlint":"^1.0.1","@stryker-mutator/core":"^9.6.1","@stryker-mutator/vitest-runner":"^9.6.1","@types/node":"^26.1.2","@vitest/coverage-v8":"^4.1.10","oxlint":"^1.77.0","prettier":"^3.9.6","typescript":"^7.0.2","vitest":"^4.1.10"},"publishConfig":{"access":"public"},"scripts":{"build":"rm -Rf dist && tsc","cs-fix":"prettier --write src tests","cs":"prettier --check src tests","infection":"stryker run","lint-fix":"oxlint --fix src tests vitest.config.ts","lint":"oxlint src tests vitest.config.ts","test":"vitest"},"_nodeVersion":"24.20.0","_id":"@chubbyts/chubbyts-undici-rate-limit@1.2.0","dist":{"integrity":"sha512-/NkH8GwsMUQ75Kzmv9N4ARSTGldA1TuT0gbjG1Ngmo9juqF/0raDwXG5sqnnimadGxjI0dB6r5lhwwCjUD+pYA==","shasum":"2027644962b4cc94d5d1fd42244a40385f6b5cb5","tarball":"https://registry.npmjs.org/@chubbyts/chubbyts-undici-rate-limit/-/chubbyts-undici-rate-limit-1.2.0.tgz","fileCount":9,"unpackedSize":32309,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD/tOIQA7o9YfxZ3laJno7ck8yFgl17oAGLVl/M7GSQaAIhAO7MxBtIwold2zw7GspF7PGl2Xl9UekEJzKGn6P20/gT"}]},"_npmUser":{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"},"directories":{},"maintainers":[{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/chubbyts-undici-rate-limit_1.2.0_1788116344252_0.49088441995577403"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-30T11:22:10.033Z","modified":"2026-08-30T18:59:04.574Z","1.0.0":"2026-08-30T11:22:10.408Z","1.1.0":"2026-08-30T16:34:28.465Z","1.2.0":"2026-08-30T18:59:04.395Z"},"author":"Dominik Zogg","license":"MIT","keywords":["chubbyts","middleware","rate-limit","rate-limiter","rate-limiter-flexible","throttle","undici"],"repository":{"type":"git","url":"chubbyts/chubbyts-undici-rate-limit"},"description":"A minimal rate limiting middleware for chubbyts-undici-server.","maintainers":[{"name":"dominikzogg","email":"dominik.zogg@ikmail.com"}],"readme":"# chubbyts-undici-rate-limit\n\n[![CI](https://github.com/chubbyts/chubbyts-undici-rate-limit/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/chubbyts/chubbyts-undici-rate-limit/actions/workflows/ci.yml)\n[![Coverage Status](https://coveralls.io/repos/github/chubbyts/chubbyts-undici-rate-limit/badge.svg?branch=master)](https://coveralls.io/github/chubbyts/chubbyts-undici-rate-limit?branch=master)\n[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fchubbyts%2Fchubbyts-undici-rate-limit%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/chubbyts/chubbyts-undici-rate-limit/master)\n[![npm-version](https://img.shields.io/npm/v/@chubbyts/chubbyts-undici-rate-limit.svg)](https://www.npmjs.com/package/@chubbyts/chubbyts-undici-rate-limit)\n\n[![bugs](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=bugs)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![code_smells](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=code_smells)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![coverage](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=coverage)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![duplicated_lines_density](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![ncloc](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=ncloc)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![sqale_rating](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![alert_status](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=alert_status)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![reliability_rating](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![security_rating](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=security_rating)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![sqale_index](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=sqale_index)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n[![vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_chubbyts-undici-rate-limit&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=chubbyts_chubbyts-undici-rate-limit)\n\n## Description\n\nA minimal rate limiting middleware for chubbyts-undici-server.\n\n## Requirements\n\n * node: >=22\n * [@chubbyts/chubbyts-dic-config-factory][5]: ^1.0.0\n * [@chubbyts/chubbyts-dic-types][3]: ^2.3.0\n * [@chubbyts/chubbyts-http-error][9]: ^3.5.0\n * [@chubbyts/chubbyts-undici-server][2]: ^1.2.0\n * [rate-limiter-flexible][6]: ^11.2.0\n\n## Installation\n\nThrough [NPM](https://www.npmjs.com) as [@chubbyts/chubbyts-undici-rate-limit][1].\n\n```ts\nnpm i @chubbyts/chubbyts-undici-rate-limit@^1.2.0\n```\n\n## Usage\n\nThe middleware is a thin layer on top of [rate-limiter-flexible][6]: it resolves the key of a request (usually the\nclient ip), consumes one point from a `RateLimiter*` and translates the result into the `ratelimit-limit`,\n`ratelimit-remaining` and `ratelimit-reset` (seconds) headers, or throws a `TooManyRequests` http error of\n[chubbyts-http-error][9] once the limiter rejects. With `duration: 0` (the limit never resets) `ratelimit-reset` is\nomitted.\n\nThe header names follow the widely supported earlier drafts of [draft-ietf-httpapi-ratelimit-headers][8] (separate\n`ratelimit-*` headers); the current drafts fold them into a single structured `ratelimit` header, which is not\nsupported by most clients yet.\n\n```ts\nimport {\n  createAttributeKeyResolver,\n  createHeaderKeyResolver,\n  createKeyResolver,\n} from '@chubbyts/chubbyts-undici-rate-limit/dist/key-resolver';\nimport { createRateLimitMiddleware } from '@chubbyts/chubbyts-undici-rate-limit/dist/middleware';\nimport { Handler, Response, ServerRequest } from '@chubbyts/chubbyts-undici-server/dist/server';\nimport { RateLimiterMemory } from 'rate-limiter-flexible';\n\nconst rateLimitMiddleware = createRateLimitMiddleware(\n  // the first resolved key wins, the last resolver should resolve a key for every request\n  createKeyResolver([createAttributeKeyResolver('clientIp'), createHeaderKeyResolver('x-api-key')]),\n  // 100 requests per 60 seconds, see rate-limiter-flexible for blockDuration, RateLimiterRedis, RateLimiterMongo, ...\n  new RateLimiterMemory({ points: 100, duration: 60 }),\n);\n\nconst handler: Handler = async (serverRequest: ServerRequest) => {\n  return new Response();\n};\n\n(async () => {\n  const serverRequest = new ServerRequest('https://example.com');\n  const response = await rateLimitMiddleware(serverRequest, handler);\n})();\n```\n\n### Client ip behind a proxy\n\nThe middleware does **not** parse `x-forwarded-for` (or any other forwarded header) itself: every proxy *appends* the\naddress it saw, so the first entry is whatever the client sent, and any client could pick its own key (and thereby its\nown limit). Use [@chubbyts/chubbyts-undici-trusted-proxy][7] in front of this middleware instead: it decides which\nentries of the forwarded headers to trust and sets the `clientIp` attribute, which `createAttributeKeyResolver('clientIp')`\nreads.\n\n```ts\nimport { createForwardedResolver, createTrustedProxyMiddleware } from '@chubbyts/chubbyts-undici-trusted-proxy/dist/middleware';\n\n// the ips / cidrs of the proxies, see @chubbyts/chubbyts-undici-trusted-proxy\nconst trustedProxyMiddleware = createTrustedProxyMiddleware(createForwardedResolver(['10.0.0.0/8', '::1']));\n\n// the trusted proxy middleware must run before the rate limit middleware\nconst middlewares = [trustedProxyMiddleware, rateLimitMiddleware];\n```\n\n`createHeaderKeyResolver` is meant for headers the client legitimately owns, like an `x-api-key` (the header value is\nthe key as is), not for forwarded headers. Keep in mind that a client who simply omits such a header gets no key and thereby passes unlimited: either\nchain a resolver with a key every request has (e.g. `createAttributeKeyResolver('clientIp')`, or as a last resort\n`createStaticKeyResolver('global')`, which puts all remaining requests into one shared limit) behind it, or reject\nrequests without the header before this middleware.\n\nThe key space should not be under the control of the client: every distinct key allocates its own counter in the\nlimiter (for `RateLimiterMemory` a record plus a timer per key until the duration ends). A resolver which lets a\nclient pick arbitrary keys (like a freely spoofable header) lets it grow the memory of the limiter without bound.\n\nA `KeyResolver` may be async (e.g. to map an api key to a tenant). The middleware fails closed: a request without a\nresolved key (no matching header / attribute) is treated as a misconfiguration and fails with an error instead of\npassing unlimited, as do errors of the limiter (e.g. an unreachable redis; use the `insuranceLimiter` option of\n[rate-limiter-flexible][6] to fall back to another limiter). To exempt requests from the rate limit, do not run the\nmiddleware for them (e.g. register it per route or route group).\n\n### Shared limits between processes\n\n`RateLimiterMemory` counts within a single process. Pass any other limiter of [rate-limiter-flexible][6]\n(`RateLimiterRedis`, `RateLimiterMongo`, `RateLimiterPostgres`, ...) to share the limits:\n\n```ts\nimport { RateLimiterMongo } from 'rate-limiter-flexible';\n\nconst rateLimiter = new RateLimiterMongo({ storeClient: mongoClient, points: 100, duration: 60 });\n```\n\n### Limit exceeded\n\nOnce the limit is exceeded the middleware does not return a response, it throws a `429 Too Many Requests` `HttpError`\n(`createTooManyRequests` of [chubbyts-http-error][9]), so that the error middleware of the application (e.g. the one\nof [chubbyts-api][10]) turns it into the response and rate limit errors look like every other error (problem json,\nlogging, ...). The error carries as data:\n\n * `limit`, `remaining`, `reset` (seconds) and `retryAfter` (seconds, at least `1`) as additional problem details,\n   `reset` and `retryAfter` are absent if the limit never resets (`duration: 0`)\n * `headers`: the `ratelimit-limit`, `ratelimit-remaining`, `ratelimit-reset` and `retry-after` headers of the `429`\n   response, ready to be set by the error middleware (the reset and retry-after ones only if the limit resets at all),\n   never part of the body\n\n```ts\nimport { isHttpError } from '@chubbyts/chubbyts-http-error/dist/http-error';\n\nconst errorMiddleware: Middleware = async (request, handler) => {\n  try {\n    return await handler(request);\n  } catch (e) {\n    if (isHttpError(e)) {\n      const { headers, _httpError, ...body } = e;\n\n      return new Response(JSON.stringify(body), {\n        status: e.status,\n        headers: { 'content-type': 'application/problem+json', ...headers },\n      });\n    }\n\n    throw e;\n  }\n};\n```\n\n### Service factories (chubbyts-dic-config)\n\nThe package ships service factories (abstract factories built on [chubbyts-dic-config-factory][5]) for a [chubbyts-dic-config][4] (or any [chubbyts-dic-types][3] compatible) container within `@chubbyts/chubbyts-undici-rate-limit/dist/service-factory`, configured through `config.chubbyts.rateLimit`:\n\n```ts\nimport type { ConfigFactory } from '@chubbyts/chubbyts-dic-config/dist/dic-config';\nimport { createContainerByConfigFactory } from '@chubbyts/chubbyts-dic-config/dist/dic-config';\nimport type { RateLimitConfig } from '@chubbyts/chubbyts-undici-rate-limit/dist/service-factory';\nimport { rateLimitMiddlewareServiceFactory } from '@chubbyts/chubbyts-undici-rate-limit/dist/service-factory';\nimport type { Middleware } from '@chubbyts/chubbyts-undici-server/dist/server';\n\nconst container = createContainerByConfigFactory({\n  chubbyts: {\n    rateLimit: {\n      // the key resolvers in order, the first resolved key wins\n      keys: [\n        // the clientIp attribute set by @chubbyts/chubbyts-undici-trusted-proxy (registered before this middleware)\n        { attribute: 'clientIp' },\n        // a header name, e.g. an api key (not x-forwarded-for, see \"Client ip behind a proxy\")\n        { header: 'x-api-key' },\n        // a fixed key for all remaining requests (one shared limit instead of no limit), optional\n        { static: 'global' },\n      ],\n      points: 100,\n      duration: 60,\n      // blockDuration: 0,\n      // keyPrefix: 'rlflx', ('rlflx:<name>' for named factories, see below)\n    } satisfies RateLimitConfig,\n  },\n  dependencies: {\n    factories: new Map<string, ConfigFactory>([['rateLimitMiddleware', rateLimitMiddlewareServiceFactory()]]),\n  },\n})();\n\nconst rateLimitMiddleware = container.get<Middleware>('rateLimitMiddleware');\n```\n\nThe `rateLimitMiddlewareServiceFactory` uses the services `rateLimitKeyResolver` and `rateLimitRateLimiter` of the container if registered, and creates them through the shipped `keyResolverServiceFactory` and `rateLimiterServiceFactory` (a `RateLimiterMemory`) otherwise. Register any of them under its name to replace it (e.g. a `RateLimiterMongo` as `rateLimitRateLimiter`) or to share it with other services.\n\n#### With names\n\nTo serve different parts of an api with different limits, the same factories can be registered multiple times with a name: the config is then read from `config.chubbyts.rateLimit.<name>` and the name gets appended to each service id (`rateLimitMiddlewareapi`, `rateLimitRateLimiterapi`, ...).\n\n```ts\nconst container = createContainerByConfigFactory({\n  chubbyts: {\n    rateLimit: {\n      api: { keys: [{ attribute: 'clientIp' }], points: 1000, duration: 60 },\n      login: { keys: [{ attribute: 'clientIp' }], points: 5, duration: 300, blockDuration: 900 },\n    } satisfies Record<string, RateLimitConfig>,\n  },\n  dependencies: {\n    factories: new Map<string, ConfigFactory>([\n      ['rateLimitMiddlewareapi', rateLimitMiddlewareServiceFactory('api')],\n      ['rateLimitMiddlewarelogin', rateLimitMiddlewareServiceFactory('login')],\n    ]),\n  },\n})();\n\nconst apiRateLimitMiddleware = container.get<Middleware>('rateLimitMiddlewareapi');\nconst loginRateLimitMiddleware = container.get<Middleware>('rateLimitMiddlewarelogin');\n```\n\nWithout an explicit `keyPrefix` a named limiter uses `rlflx:<name>`, so that named limiters sharing one store (e.g. a\nredis) do not share their counters.\n\n## Copyright\n\n2026 Dominik Zogg\n\n[1]: https://www.npmjs.com/package/@chubbyts/chubbyts-undici-rate-limit\n[2]: https://www.npmjs.com/package/@chubbyts/chubbyts-undici-server\n[3]: https://www.npmjs.com/package/@chubbyts/chubbyts-dic-types\n[4]: https://www.npmjs.com/package/@chubbyts/chubbyts-dic-config\n[5]: https://www.npmjs.com/package/@chubbyts/chubbyts-dic-config-factory\n[6]: https://www.npmjs.com/package/rate-limiter-flexible\n[7]: https://www.npmjs.com/package/@chubbyts/chubbyts-undici-trusted-proxy\n[8]: https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/\n[9]: https://www.npmjs.com/package/@chubbyts/chubbyts-http-error\n[10]: https://www.npmjs.com/package/@chubbyts/chubbyts-api\n","readmeFilename":""}