Skip to content

JhonaCodes/rate-limiter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rate_limiter

A reusable rate-limiting toolkit for actix-web.

It provides two complementary approaches:

  1. Adaptive limiter (RateLimiter) Applies per-route policies with penalty levels, progressive lockout, and observability headers.
  2. Global limiter (global) Applies a single per-IP quota for the scope where the middleware is mounted.

Features

  • Route-prefix and method-aware policies (RouteRule, MethodScope)
  • Per-policy profiles (PolicySpec) with optional sensitive mode
  • Identity bucketing by IP + credential fingerprint (X-Api-Key, Authorization, X-Device-Id)
  • Extra hard-limit protection
  • Standard headers in rate-limited responses

Units (Important)

PolicySpec::new(key, sensitive, base_rps, base_burst) uses requests per second (RPS), not milliseconds.

Internally:

interval_ms = ceil(1000 / base_rps)

Examples:

  • PolicySpec::new("auth", true, 6, 36) => 6 rps (~167ms between requests), burst 36
  • PolicySpec::new("mcp_write", false, 120, 360) => 120 rps (~9ms between requests), burst 360

If you prefer time-based configuration, use:

  • PolicySpec::from_interval_ms(...)
  • PolicySpec::from_interval_secs(...)

Installation

Option A: crates.io (once published)

[dependencies]
rate_limiter = "0.1"

Option B: Git dependency

[dependencies]
rate_limiter = { git = "https://github.com/JhonaCodes/rate-limiter" }

Option C: local path (monorepo)

[dependencies]
rate_limiter = { path = "../rate_limiter" }

Quick Start: Adaptive limiter

use actix_web::{App, HttpServer};
use rate_limiter::{MethodScope, PolicySpec, RateLimiter, RouteRule};

let policies = vec![
    PolicySpec::new("auth", true, 5, 30),
    PolicySpec::new("default", false, 20, 100),
];

let rules = vec![
    RouteRule::new("auth", vec!["/v1/auth/"], MethodScope::Any),
    RouteRule::new("default", vec!["/v1/"], MethodScope::Any),
];

let limiter = RateLimiter::new(policies, rules);

HttpServer::new(move || {
    App::new()
        .wrap(limiter.middleware())
        // .configure(api::config)
});

Quick Start: Global limiter

use actix_web::App;
use rate_limiter::{global, GlobalIpStrategy};

let app = App::new()
    .wrap(global(1, 20, GlobalIpStrategy::RealIp));
// average 1 request/second, burst 20

When to use which

  • Use RateLimiter when you need endpoint-level rules (for example, /auth stricter than /public).
  • Use global(...) for a simple perimeter limit by IP.
  • You can combine both: global outside + adaptive inside domain routes.

Added headers

When limiting/control is active, responses may include:

  • x-ratelimit-level
  • x-ratelimit-policy
  • x-ratelimit-after
  • Retry-After

Block response

Returns 429 Too Many Requests with JSON payload:

{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Please retry later.",
  "retry_after_seconds": 3
}

Public API

  • RateLimiter
  • PolicySpec
  • RouteRule
  • MethodScope
  • global
  • GlobalIpStrategy

Run the example

cargo run --example actix_basic

Test server: http://127.0.0.1:8081

Notes

  • The library is domain-agnostic and does not hardcode business routes.
  • Route-to-policy mapping is defined by each application.
  • Designed for Rust edition 2024.

About

Domain-agnostic rate limiting for Actix Web: adaptive per-route policies + global IP limiter, progressive lockout, and rate-limit observability headers.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages