axum_governor/lib.rs
1/* src/lib.rs */
2
3//! # Axum Governor
4//!
5//! A rate-limiting middleware for Axum, powered by `lazy-limit` and `real`.
6//!
7//! This crate provides a simple and configurable Tower layer to enforce rate limits
8//! on your Axum application based on the client's real IP address.
9//!
10//! ## Features
11//!
12//! - **IP-Based Limiting**: Uses the `real` crate to accurately identify the client's IP address.
13//! - **Flexible Rules**: Leverages `lazy-limit` to support global and route-specific rate limits.
14//! - **Two Modes**: Supports both standard mode (respecting global and route rules) and override mode (ignoring global rules).
15//! - **Easy Integration**: Implemented as a standard Tower `Layer`.
16//!
17//! ## Quick Start
18//!
19//! 1. **Add Dependencies**:
20//!
21//! ```toml
22//! [dependencies]
23//! axum-governor = "0.1.0"
24//! lazy-limit = "1"
25//! tokio = { version = "1", features = ["full"] }
26//! real = { version = "0.1", features = ["axum"] }
27//! ```
28//!
29//! 2. **Initialize the Rate Limiter**:
30//!
31//! Before starting your application, initialize `lazy-limit` with your desired rules.
32//!
33//! ```rust
34//! use lazy_limit::{init_rate_limiter, Duration, RuleConfig};
35//!
36//! #[tokio::main]
37//! async fn main() {
38//! init_rate_limiter!(
39//! default: RuleConfig::new(Duration::seconds(1), 5), // 5 req/s globally
40//! routes: [
41//! ("/api/special", RuleConfig::new(Duration::seconds(1), 10)),
42//! ]
43//! ).await;
44//!
45//! // ... your Axum app setup
46//! }
47//! ```
48//!
49//! 3. **Add Layers to Your Router**:
50//!
51//! The `GovernorLayer` requires the `RealIpLayer` to be present. Always add `RealIpLayer` first.
52//!
53//! ```rust
54//! # use axum::{Router, routing::get};
55//! # use axum_governor::GovernorLayer;
56//! # use real::RealIpLayer;
57//! # use std::net::SocketAddr;
58//! # async fn handler() -> &'static str { "Hello!" }
59//! # async {
60//! let app = Router::new()
61//! .route("/", get(handler))
62//! .layer(
63//! tower::ServiceBuilder::new()
64//! .layer(RealIpLayer::default()) // Extracts the real IP
65//! .layer(GovernorLayer::default()) // Applies rate limiting
66//! );
67//!
68//! let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
69//! let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
70//! axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>())
71//! .await
72//! .unwrap();
73//! # };
74//! ```
75
76use axum::http::Method;
77use lazy_limit::HttpMethod;
78
79// Public exports
80pub use config::GovernorConfig;
81pub use layer::GovernorLayer;
82pub use middleware::GovernorMiddleware;
83
84// Module declarations
85mod config;
86mod layer;
87mod middleware;
88
89pub fn map_method(m: Method) -> HttpMethod {
90 match m {
91 Method::GET => HttpMethod::GET,
92 Method::POST => HttpMethod::POST,
93 Method::PUT => HttpMethod::PUT,
94 Method::DELETE => HttpMethod::DELETE,
95 Method::PATCH => HttpMethod::PATCH,
96 Method::HEAD => HttpMethod::HEAD,
97 Method::OPTIONS => HttpMethod::OPTIONS,
98 Method::CONNECT => HttpMethod::CONNECT,
99 Method::TRACE => HttpMethod::TRACE,
100 _ => HttpMethod::OTHER,
101 }
102}