Crate axum_gcra

Source
Expand description

§axum_gcra

GCRA-based Rate Limiter for Axum with per-route/per-key rate limiting.

crates.io Documentation MIT/Apache-2 licensed

§Summary

This crate provides a robust implementation of a rate-limiting Layer and Service for axum using the GCRA algorithm, which allows for average throughput and burst request limiting. Rather than providing a global rate-limiter for all routes, this crate allows for individual routes/paths to be configured with separate rate-limiting quotas and for the extraction of arbitrary keys from the request for additional compartmentalization.

For example:

use std::time::Duration;

use axum::{routing::get, Router, http::Method};
use axum_gcra::{gcra::Quota, RateLimitLayer, real_ip::RealIp};

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(|| async { "Hello, World!" }))
        .route("/hello", get(|| async { "Hello, Again!" }))
        .route_layer(
            RateLimitLayer::<RealIp>::builder()
                .with_default_quota(Quota::simple(Duration::from_secs(5)))
                .with_route((Method::GET, "/"), Quota::simple(Duration::from_secs(1)))
                .with_route((Method::GET, "/hello"), Quota::simple(Duration::from_secs(2)))
                .with_global_fallback(true)
                .with_extension(true)
                .default_handle_error(),
        );

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

§Keys

In order for the rate limiter to be able to differentiate between different clients, the RateLimitLayer can be configured with single or composite keys that are extracted from the request. For example, to rate limit based on the client’s IP address, the following could be used with the provided RealIp extractor:

use axum::{routing::get, Router, extract::Extension};
use axum_gcra::{RateLimitLayer, real_ip::RealIp, extensions::RateLimiter};

type Key = RealIp; // could also be `(RealIp, UserSession)`, for example.

let app = Router::<()>::new()
    // keys are any type that can implement `FromRequestParts` and `axum_gcra::Key`
    .route("/", get(|ip: RealIp| async move { format!("Hello, {ip}!") }))
    // The key type must also be specified when extracting the `RateLimiter` extension.
    .route("/extension", get(|rl: Extension<RateLimiter<Key>>| async move {
        // do something with the rate limiter, etc.
        "Hello, Extensions!"
    }))
    .route_layer(RateLimitLayer::<Key>::builder().default_handle_error());

Please read the documentation for RealIp for more information.

§Garbage Collection

Internally, the rate limiter uses a shared hash map structure to store the state of each key. To avoid it growing indefinitely, a garbage collection mechanism is provided that will remove entries that have expired and no longer needed. This can be configured to run based on the number of requests processed or on a fixed time interval in a background task. For example:

use std::time::Duration;
use axum::{routing::get, Router};
use axum_gcra::{RateLimitLayer, real_ip::RealIp};

let app = Router::<()>::new()
    .route("/", get(|| async { "Hello, World!" }))
    .route_layer(
        RateLimitLayer::<RealIp>::builder()
            .with_gc_interval(1000) // run GC on every 1000th request
            .with_gc_interval(Duration::from_secs(60)) // or run every 60 seconds
            .default_handle_error(),
    );

See the docs for GCInterval for more information.

Re-exports§

pub use gcra::RateLimitError;

Modules§

extensions
Defines the RateLimiter extension for the request’s extensions, extractable with Extension<RateLimiter<Key>>.
gcra
Lower-level rate limiter implementation using the Generic Cell Rate Algorithm (GCRA) and an asynchronous hash map for concurrent access.
real_ipreal_ip
Provides a way to get the real IP address of the client, to the best of our ability.

Structs§

RateLimitLayer
Rate limiter Layer for axum.
RateLimitLayerBuilder
Builder for the rate limiter layer.
RateLimitService
Rate limiter Service for axum.
Route
A route for rate limiting, consisting of a path and method.

Enums§

Error
Error wrapper for rate limiting errors or inner service errors.
GCInterval
Interval for garbage collection of the rate limiter, which can be either a number of requests or a time duration.

Traits§

Key
Trait for user-provided keys used to identify rate limiter entries.