limifyrate 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- limifyrate-0.1.3/LICENSE +21 -0
- limifyrate-0.1.3/PKG-INFO +388 -0
- limifyrate-0.1.3/README.md +356 -0
- limifyrate-0.1.3/limify/__init__.py +7 -0
- limifyrate-0.1.3/limify/adapters/__init__.py +0 -0
- limifyrate-0.1.3/limify/adapters/fastapi/__init__.py +0 -0
- limifyrate-0.1.3/limify/adapters/fastapi/context.py +28 -0
- limifyrate-0.1.3/limify/adapters/fastapi/middleware.py +34 -0
- limifyrate-0.1.3/limify/adapters/fastapi/tests/test_build_request_context.py +102 -0
- limifyrate-0.1.3/limify/adapters/fastapi/tests/test_fastapi_middleware.py +113 -0
- limifyrate-0.1.3/limify/config.py +8 -0
- limifyrate-0.1.3/limify/core/__init__.py +0 -0
- limifyrate-0.1.3/limify/core/algorithms/base.py +21 -0
- limifyrate-0.1.3/limify/core/algorithms/token_bucket.py +113 -0
- limifyrate-0.1.3/limify/core/context.py +12 -0
- limifyrate-0.1.3/limify/core/limify.py +36 -0
- limifyrate-0.1.3/limify/core/limiter.py +41 -0
- limifyrate-0.1.3/limify/core/path.py +62 -0
- limifyrate-0.1.3/limify/core/plans.py +7 -0
- limifyrate-0.1.3/limify/core/redis_adapter.py +48 -0
- limifyrate-0.1.3/limify/core/reservation.py +0 -0
- limifyrate-0.1.3/limify/core/resolvers/key_resolver.py +54 -0
- limifyrate-0.1.3/limify/core/resolvers/plan_resolver.py +18 -0
- limifyrate-0.1.3/limify/core/resolvers/rule_resolver.py +16 -0
- limifyrate-0.1.3/limify/core/rules.py +32 -0
- limifyrate-0.1.3/limify/defaults.py +15 -0
- limifyrate-0.1.3/limify/plan_provider.py +3 -0
- limifyrate-0.1.3/limify/user_rules.py +12 -0
- limifyrate-0.1.3/limifyrate.egg-info/PKG-INFO +388 -0
- limifyrate-0.1.3/limifyrate.egg-info/SOURCES.txt +33 -0
- limifyrate-0.1.3/limifyrate.egg-info/dependency_links.txt +1 -0
- limifyrate-0.1.3/limifyrate.egg-info/requires.txt +8 -0
- limifyrate-0.1.3/limifyrate.egg-info/top_level.txt +1 -0
- limifyrate-0.1.3/pyproject.toml +69 -0
- limifyrate-0.1.3/setup.cfg +4 -0
limifyrate-0.1.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pedram Aliniaye Asli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: limifyrate
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Framework-agnostic, Redis-backed rate limiting engine for modern async Python systems.
|
|
5
|
+
Author: Pedram Aliniaye Asli
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/pedram-aliniaye-asli/limify
|
|
8
|
+
Project-URL: Repository, https://github.com/pedram-aliniaye-asli/limify
|
|
9
|
+
Project-URL: Documentation, https://github.com/pedram-aliniaye-asli/limify
|
|
10
|
+
Keywords: rate limiting,redis,async,token bucket,fastapi,starlette,api,microservices,middleware
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: redis>=7.0.0
|
|
26
|
+
Provides-Extra: fastapi
|
|
27
|
+
Requires-Dist: starlette>=0.27; extra == "fastapi"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# Limify
|
|
34
|
+
|
|
35
|
+
Framework-agnostic, Redis-backed rate limiting engine for modern Python systems.
|
|
36
|
+
|
|
37
|
+
Limify provides a clean-architecture rate limiting core with pluggable storage adapters, async and sync support, atomic Redis Lua execution, and framework adapters.
|
|
38
|
+
|
|
39
|
+
Limify is designed as infrastructure-level software for backend engineers, microservices, and API platforms.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
* Framework-agnostic core
|
|
46
|
+
* Async and sync Redis support
|
|
47
|
+
* Atomic Redis Lua token bucket implementation
|
|
48
|
+
* FastAPI / Starlette middleware adapter
|
|
49
|
+
* Rule-based rate limiting with wildcard matching
|
|
50
|
+
* Plan-based rate limiting support
|
|
51
|
+
* Multi-identity support:
|
|
52
|
+
|
|
53
|
+
* user_id
|
|
54
|
+
* org_id
|
|
55
|
+
* api_key
|
|
56
|
+
* client_ip
|
|
57
|
+
* Clean architecture with dependency injection
|
|
58
|
+
* Pluggable storage and algorithms
|
|
59
|
+
* Fully testable design
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Architecture
|
|
64
|
+
|
|
65
|
+
Limify uses layered clean architecture:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
Application (FastAPI / Flask / etc.)
|
|
69
|
+
↓
|
|
70
|
+
Adapter (Middleware)
|
|
71
|
+
↓
|
|
72
|
+
Limiter (Orchestrator)
|
|
73
|
+
↓
|
|
74
|
+
Resolvers
|
|
75
|
+
├─ RuleResolver
|
|
76
|
+
├─ PlanResolver
|
|
77
|
+
└─ KeyResolver
|
|
78
|
+
↓
|
|
79
|
+
Algorithm (Token Bucket)
|
|
80
|
+
↓
|
|
81
|
+
Storage Adapter (Redis)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Core is fully independent of frameworks.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
### Core only
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
pip install limifyrate
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### With FastAPI / Starlette adapter
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
pip install "limifyrate[fastapi]"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Development install
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
git clone https://github.com/pedram-aliniaye-asli/limify.git
|
|
106
|
+
cd limify
|
|
107
|
+
pip install -e ".[dev]"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Requirements
|
|
113
|
+
|
|
114
|
+
* Python 3.10+
|
|
115
|
+
* Redis
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Quick Start (Async)
|
|
120
|
+
|
|
121
|
+
Example using async Redis and FastAPI.
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import redis.asyncio as redis
|
|
125
|
+
|
|
126
|
+
from fastapi import FastAPI
|
|
127
|
+
from limify import Limify, LimifyConfig
|
|
128
|
+
from limify.adapters.fastapi.middleware import LimifyMiddleware
|
|
129
|
+
from limify.core.redis_adapter import RedisAsyncAdapter
|
|
130
|
+
from limify.core.algorithms.token_bucket import AsyncTokenBucketAlgorithm
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
redis_client = redis.from_url("redis://localhost:6379")
|
|
134
|
+
|
|
135
|
+
adapter = RedisAsyncAdapter(redis_client)
|
|
136
|
+
|
|
137
|
+
algorithm = AsyncTokenBucketAlgorithm(adapter)
|
|
138
|
+
await algorithm.initialize()
|
|
139
|
+
|
|
140
|
+
config = LimifyConfig(
|
|
141
|
+
rules=[
|
|
142
|
+
{
|
|
143
|
+
"id": "default",
|
|
144
|
+
"method": "*",
|
|
145
|
+
"path": "/**", # This rule will include all requests with different methods on all endpoints and it's not suggested really! Just for demonstration purposes!
|
|
146
|
+
"rate": "5/minute",
|
|
147
|
+
"priority": 0,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"id": "items",
|
|
151
|
+
"method": "*",
|
|
152
|
+
"path": "/items",
|
|
153
|
+
"rate": "10/minute",
|
|
154
|
+
"priority": 10,
|
|
155
|
+
},
|
|
156
|
+
]
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
limify = Limify(
|
|
160
|
+
algorithm=algorithm,
|
|
161
|
+
config=config,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
app = FastAPI()
|
|
165
|
+
|
|
166
|
+
app.add_middleware(
|
|
167
|
+
LimifyMiddleware,
|
|
168
|
+
limiter=limify.limiter,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@app.get("/items")
|
|
173
|
+
async def items():
|
|
174
|
+
return {"status": "ok"}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Sync Example
|
|
180
|
+
|
|
181
|
+
Example using synchronous Redis.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
import redis
|
|
185
|
+
|
|
186
|
+
from limify import Limify, LimifyConfig
|
|
187
|
+
from limify.core.redis_adapter import RedisSyncAdapter
|
|
188
|
+
from limify.core.algorithms.token_bucket import TokenBucketAlgorithm
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
redis_client = redis.Redis(host="localhost", port=6379)
|
|
192
|
+
|
|
193
|
+
adapter = RedisSyncAdapter(redis_client)
|
|
194
|
+
|
|
195
|
+
algorithm = TokenBucketAlgorithm(adapter)
|
|
196
|
+
|
|
197
|
+
config = LimifyConfig(
|
|
198
|
+
rules=[
|
|
199
|
+
{
|
|
200
|
+
"id": "default",
|
|
201
|
+
"method": "*",
|
|
202
|
+
"path": "/**",
|
|
203
|
+
"rate": "5/minute",
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
limify = Limify(
|
|
209
|
+
algorithm=algorithm,
|
|
210
|
+
config=config,
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Redis Key Structure
|
|
217
|
+
|
|
218
|
+
Limify generates deterministic keys:
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
limify:{rule_id}:{plan_id}:{identity_type}:{identity_value}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Examples:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
limify:items:default:user:42
|
|
228
|
+
limify:default:default:ip:127.0.0.1
|
|
229
|
+
limify:items:pro:apikey:abc123
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Each identity and rule has an independent token bucket.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Rules
|
|
237
|
+
|
|
238
|
+
Rules define rate limits per endpoint.
|
|
239
|
+
|
|
240
|
+
Example:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
{
|
|
244
|
+
"id": "items",
|
|
245
|
+
"method": "*",
|
|
246
|
+
"path": "/items",
|
|
247
|
+
"rate": "10/minute",
|
|
248
|
+
"priority": 10,
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Supported wildcards:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
/items/*
|
|
256
|
+
/api/**
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Higher priority rules override lower priority ones.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Identity Resolution Priority
|
|
264
|
+
|
|
265
|
+
Default resolution order:
|
|
266
|
+
|
|
267
|
+
1. user_id
|
|
268
|
+
2. org_id
|
|
269
|
+
3. api_key
|
|
270
|
+
4. client_ip
|
|
271
|
+
5. anonymous
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Plan Support
|
|
276
|
+
|
|
277
|
+
Limify supports plan-based rate limiting using PlanProvider.
|
|
278
|
+
|
|
279
|
+
This enables multi-tier SaaS limits.
|
|
280
|
+
|
|
281
|
+
Example plans:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
free → 10/minute
|
|
285
|
+
pro → 100/minute
|
|
286
|
+
enterprise → 1000/minute
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Algorithms
|
|
292
|
+
|
|
293
|
+
Currently implemented:
|
|
294
|
+
|
|
295
|
+
* Token Bucket (async)
|
|
296
|
+
* Token Bucket (sync)
|
|
297
|
+
|
|
298
|
+
Future:
|
|
299
|
+
|
|
300
|
+
* Sliding Window
|
|
301
|
+
* Fixed Window
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Storage Adapters
|
|
306
|
+
|
|
307
|
+
Currently implemented:
|
|
308
|
+
|
|
309
|
+
* RedisAsyncAdapter
|
|
310
|
+
* RedisSyncAdapter
|
|
311
|
+
|
|
312
|
+
Future:
|
|
313
|
+
|
|
314
|
+
* In-memory adapter
|
|
315
|
+
* PostgreSQL adapter
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## FastAPI Adapter
|
|
320
|
+
|
|
321
|
+
Limify provides Starlette-compatible middleware.
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
limify.adapters.fastapi.middleware.LimifyMiddleware
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Adds headers:
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
X-RateLimit-Limit
|
|
331
|
+
X-RateLimit-Remaining
|
|
332
|
+
Retry-After
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Project Structure
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
limify/
|
|
341
|
+
adapters/
|
|
342
|
+
fastapi/
|
|
343
|
+
core/
|
|
344
|
+
algorithms/
|
|
345
|
+
resolvers/
|
|
346
|
+
redis_adapter.py
|
|
347
|
+
limiter.py
|
|
348
|
+
...
|
|
349
|
+
config.py
|
|
350
|
+
defaults.py
|
|
351
|
+
plan_provider.py
|
|
352
|
+
...
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Status
|
|
358
|
+
|
|
359
|
+
Alpha
|
|
360
|
+
|
|
361
|
+
Core architecture is stable and production-grade, but API surface may evolve.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Roadmap
|
|
366
|
+
|
|
367
|
+
* In-memory storage adapter
|
|
368
|
+
* Flask adapter
|
|
369
|
+
* Django adapter
|
|
370
|
+
* Sliding window algorithm
|
|
371
|
+
* Fixed window algorithm
|
|
372
|
+
* Metrics support
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## License
|
|
377
|
+
|
|
378
|
+
MIT License
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Author
|
|
383
|
+
|
|
384
|
+
Pedram Aliniaye Asli
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
Limify is designed as reusable infrastructure for modern backend systems.
|