Skip to content

feat: add per-user REST rate limiting middleware#341

Merged
greatest0fallt1me merged 2 commits into
CalloraOrg:mainfrom
David-patrick-chuks:feature/rest-rate-limit-middleware
May 27, 2026
Merged

feat: add per-user REST rate limiting middleware#341
greatest0fallt1me merged 2 commits into
CalloraOrg:mainfrom
David-patrick-chuks:feature/rest-rate-limit-middleware

Conversation

@David-patrick-chuks

@David-patrick-chuks David-patrick-chuks commented May 26, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR adds a per-user global REST rate limiting middleware for the authenticated API surface, separate from the existing gateway token-bucket limiter. It limits authenticated requests by user id, falls back to IP-based limiting for unauthenticated traffic, and returns 429 responses with Retry-After headers to reduce abuse on /api/billing, /api/usage, /api/developers, /api/vault, and /api/keys.

Related Issue

Closes #316

Changes

⚙️ REST Rate Limiting Middleware

  • [ADD] src/middleware/restRateLimit.ts

  • Added a dedicated in-memory REST rate limiter separate from the gateway limiter.

  • Limits requests per authenticated user id.

  • Falls back to client IP when no authenticated user id can be resolved.

  • Returns 429 Too Many Requests with Retry-After.

  • Uses TooManyRequestsError from src/errors/index.ts.

  • [MODIFY] src/middleware/requireAuth.ts

  • Extracted shared request identity resolution logic so rate limiting and auth use the same user-id derivation rules.

  • Preserves existing JWT and x-user-id auth behavior while enabling secure pre-auth rate-limit keying.

🌐 API Surface Wiring

  • [MODIFY] src/app.ts

  • Mounted the REST rate limiter on authenticated REST areas:

    • /api/usage
    • /api/developers
    • /api/vault
    • /api/keys
  • Injected the same limiter into /api/billing.

  • [MODIFY] src/routes/index.ts

  • Added router factory support so the billing router can receive the REST rate limiter without affecting public routes like /api/health and /api/apis.

🧪 Tests

  • [ADD] src/middleware/restRateLimit.test.ts

  • Added coverage for:

    • 429 responses with Retry-After
    • per-user isolation
    • shared user buckets across auth methods
    • IP fallback for unauthenticated requests
  • [MODIFY] src/config/env.test.ts

  • Added env-schema coverage for REST rate-limit defaults and validation.

  • [MODIFY] src/config/index.test.ts

  • Added config export coverage for REST rate-limit settings.

🔧 Configuration

  • [MODIFY] src/config/env.ts

  • Added:

    • REST_RATE_LIMIT_WINDOW_MS
    • REST_RATE_LIMIT_MAX_REQUESTS
  • [MODIFY] src/config/index.ts

  • Exposed parsed REST rate-limit config to application code.

  • [MODIFY] .env.example

  • Documented the new REST rate-limit environment variables.

📘 Documentation

  • [MODIFY] README.md
  • Documented the new REST rate limiting behavior and configuration.

Verification Results

Acceptance Criteria Status
Exceeding the limit returns 429 with Retry-After
Limits are per authenticated user and configurable
Unauthenticated requests fall back to IP-based limiting
Middleware is separate from the gateway token bucket
Middleware tests pass successfully
Focused REST rate limiter tests pass successfully
Typecheck passes successfully

How to Test

# 1. Confirm you're on the branch
git branch --show-current

# 2. Run middleware tests
npm test -- src/middleware

# 3. Run the focused REST rate limiter test
npx jest --runInBand --forceExit src/middleware/restRateLimit.test.ts

# 4. Verify typecheck passes
npm run typecheck

# 5. Optional: inspect the changed files
git diff -- src/middleware/restRateLimit.ts src/middleware/requireAuth.ts src/app.ts src/routes/index.ts src/config/env.ts src/config/index.ts .env.example README.md

Screenshots

✅ Middleware tests pass

A screenshot of:

npm test -- src/middleware
image

✅ Focused REST rate limiter test passes

A screenshot of:

npx jest --runInBand --forceExit src/middleware/restRateLimit.test.ts
image

✅ Typecheck passes

A screenshot of:

npm run typecheck
image

@drips-wave

drips-wave Bot commented May 26, 2026

Copy link
Copy Markdown

@David-patrick-chuks Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@greatest0fallt1me greatest0fallt1me merged commit 16d8777 into CalloraOrg:main May 27, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add per-user global REST rate limiting middleware separate from the gateway token bucket

2 participants