{"id":13822504,"url":"https://github.com/TerminalWitchcraft/actix-ratelimit","last_synced_at":"2025-05-16T17:30:55.763Z","repository":{"id":44871426,"uuid":"234469197","full_name":"TerminalWitchcraft/actix-ratelimit","owner":"TerminalWitchcraft","description":"Rate limiter framework for Actix web","archived":true,"fork":false,"pushed_at":"2023-01-03T15:54:04.000Z","size":133,"stargazers_count":127,"open_issues_count":14,"forks_count":24,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-06T01:46:43.237Z","etag":null,"topics":["actix","actix-ratelimit","actix-web","http","http-requests","rust","rust-lang"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TerminalWitchcraft.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-17T04:18:18.000Z","updated_at":"2024-11-03T17:18:47.000Z","dependencies_parsed_at":"2023-02-01T07:31:02.259Z","dependency_job_id":null,"html_url":"https://github.com/TerminalWitchcraft/actix-ratelimit","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TerminalWitchcraft%2Factix-ratelimit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TerminalWitchcraft%2Factix-ratelimit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TerminalWitchcraft%2Factix-ratelimit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TerminalWitchcraft%2Factix-ratelimit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TerminalWitchcraft","download_url":"https://codeload.github.com/TerminalWitchcraft/actix-ratelimit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254576405,"owners_count":22094363,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actix","actix-ratelimit","actix-web","http","http-requests","rust","rust-lang"],"created_at":"2024-08-04T08:02:03.197Z","updated_at":"2025-05-16T17:30:55.471Z","avatar_url":"https://github.com/TerminalWitchcraft.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"[![Travis (.org)](https://img.shields.io/travis/TerminalWitchcraft/actix-ratelimit?label=build\u0026style=for-the-badge)](https://travis-ci.com/TerminalWitchcraft/actix-ratelimit) ![Crates.io](https://img.shields.io/crates/v/actix-ratelimit?style=for-the-badge) ![Crates.io](https://img.shields.io/crates/l/actix-ratelimit?style=for-the-badge) \n# actix-ratelimit \n\n\nRate limiting middleware framework for [actix-web](https://actix.rs/)\n\nThis crate provides an asynchronous and concurrent rate limiting middleware based on [actor](https://www.wikiwand.com/en/Actor_model)\nmodel which can be wraped around an [Actix](https://actix.rs/) application. Middleware contains a store which is used to\nidentify client request.\n\nCheck out the [documentation here](https://docs.rs/actix-ratelimit/).\n\nComments, suggesstions and critiques are welcome!\n\n## Usage\nAdd this to your Cargo.toml:\n```toml\n[dependencies]\nactix-ratelimit = \"0.3.1\"\n```\n\nVersion `0.3.*` supports actix-web v3. If you're using actix-web v2, consider using version `0.2.*`.\n\nMinimal example:\n\n```rust\nuse actix_web::{web, App, HttpRequest, HttpServer, Responder};\nuse actix_ratelimit::{RateLimiter, MemoryStore, MemoryStoreActor};\nuse std::time::Duration;\n\nasync fn greet(req: HttpRequest) -\u003e impl Responder{\n    let name = req.match_info().get(\"name\").unwrap_or(\"World!\");\n    format!(\"Hello {}!\", \u0026name)\n}\n\n#[actix_web::main]\nasync fn main() -\u003e std::io::Result\u003c()\u003e {\n    // Initialize store\n    let store = MemoryStore::new();\n    HttpServer::new(move ||{\n        App::new()\n            // Register the middleware\n            // which allows for a maximum of\n            // 100 requests per minute per client\n            // based on IP address\n            .wrap(\n                RateLimiter::new(\n                MemoryStoreActor::from(store.clone()).start())\n                    .with_interval(Duration::from_secs(60))\n                    .with_max_requests(100)\n            )\n            .route(\"/\", web::get().to(greet))\n            .route(\"/{name}\", web::get().to(greet))\n    })\n    .bind(\"127.0.0.1:8000\")?\n    .run()\n    .await\n}\n```\nSending a request returns a response with the ratelimiting headers:\n```shell\n$ curl -i \"http://localhost:8000/\"\n\nHTTP/1.1 200 OK\ncontent-length: 13\ncontent-type: text/plain; charset=utf-8\nx-ratelimit-remaining: 99\nx-ratelimit-reset: 52\nx-ratelimit-limit: 100\ndate: Tue, 04 Feb 2020 21:53:27 GMT\n\nHello World!\n```\nExceeding the limit returns HTTP 429 Error code.\n\n## Stores\n\nA _store_ is a data structure, database connection or anything which can be used to store\n_ratelimit_ data associated with a _client_. A _store actor_ which acts on this store is\nresponsible for performiing all sorts of operations(SET, GET, DEL, etc). It is Important to\nnote that there are multiple store actors acting on a _single_ store.\n\n\n### List of features\n- `memory` (in-memory store based on concurrent [hashmap](https://github.com/xacrimon/dashmap))\n- `redis-store` (based on [redis-rs](https://github.com/mitsuhiko/redis-rs))\n- `memcached` (based on [r2d2-memcache](https://github.com/megumish/r2d2-memcache), see note to developers below)\n\n\n## Implementing your own store\n\nTo implement your own store, you have to implement an [Actor](https://actix.rs/actix/actix/trait.Actor.html) which can handle [ActorMessage](https://docs.rs/actix-ratelimit/0.3.1/actix_ratelimit/enum.ActorMessage.html) type\nand return [ActorResponse](https://docs.rs/actix-ratelimit/0.3.1/actix_ratelimit/enum.ActorResponse.html) type. Check the [module level documentation](https://docs.rs/actix-ratelimit/0.3.1/actix_ratelimit/stores/index.html) for\nmore details and a basic example.\n\n## Note to developers\n\n* By default, all features are enabled. To use a particular feature, for instance redis, put this in your Cargo.toml:\n```toml\n[dependencies]\nactix-ratelimit = {version = \"0.3.1\", default-features = false, features = [\"redis-store\"]}\n```\n\n* By default, the client's IP address is used as the identifier which can be customized\nusing [ServiceRequest](https://docs.rs/actix-web/3.3.2/actix_web/dev/struct.ServiceRequest.html) instance.\nFor example, using api key header to identify client:\n```rust\n#[actix_web::main]\nasync fn main() -\u003e std::io::Result\u003c()\u003e {\n    // Initialize store\n    let store = MemoryStore::new();\n    HttpServer::new(move ||{\n        App::new()\n            .wrap(\n                RateLimiter::new(\n                MemoryStoreActor::from(store.clone()).start())\n                    .with_interval(Duration::from_secs(60))\n                    .with_max_requests(100)\n                    .with_identifier(|req| {\n                        let key = req.headers().get(\"x-api-key\").unwrap();\n                        let key = key.to_str().unwrap();\n                        Ok(key.to_string())\n                    })\n            )\n            .route(\"/\", web::get().to(greet))\n            .route(\"/{name}\", web::get().to(greet))\n    })\n    .bind(\"127.0.0.1:8000\")?\n    .run()\n    .await\n}\n```\n\n* The memcache store uses a separate key to keep track of expiry since there's no way to get ttl of keys in memcache natively yet. This means memcache store will use double the number of keys as compared to redis store. If there's any better way to do this, please considering opening an issue!\n\n* It is **important** to initialize store before creating HttpServer instance, or else a store\nwill be created for each web worker. This may lead to instability and inconsistency! For\nexample, initializing your app in the following manner would create more than one stores:\n```rust\n#[actix_web::main]\nasync fn main() -\u003e std::io::Result\u003c()\u003e {\n    HttpServer::new(move ||{\n        App::new()\n            .wrap(\n                RateLimiter::new(\n                MemoryStoreActor::from(MemoryStore::new()).start())\n                    .with_interval(Duration::from_secs(60))\n                    .with_max_requests(100)\n            )\n            .route(\"/\", web::get().to(greet))\n            .route(\"/{name}\", web::get().to(greet))\n    })\n    .bind(\"127.0.0.1:8000\")?\n    .run()\n    .await\n}\n```\n\n* To enable ratelimiting across multiple instances of your web application(multiple http servers behind load balancer), consider using a feature called `session stickiness` supported by popular cloud services such as AWS, Azure, etc.\n\n\n## Status\nThis project has not reached v1.0, so some instability and breaking changes are to be expected\ntill then.\n\nYou can use the [issue tracker](https://github.com/TerminalWitchcraft/actix-ratelimit/issues) in case you encounter any problems.\n\n## LICENSE\nThis project is licensed under MIT license.\n\nLicense: MIT\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTerminalWitchcraft%2Factix-ratelimit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTerminalWitchcraft%2Factix-ratelimit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTerminalWitchcraft%2Factix-ratelimit/lists"}