summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-15 06:26:26 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-15 06:26:26 +0000
commit563eca9af65b4c52f37d1b9e1fa9b3c2d50ad60d (patch)
treedb461db70f0d41b7aba1a5f83a35d585ed6b2f9a
parent8f193a2b3d8296d6bdce9132aa2fc0cf3b5481a7 (diff)
automatic import of python-fastapi-limiter
-rw-r--r--.gitignore1
-rw-r--r--python-fastapi-limiter.spec578
-rw-r--r--sources1
3 files changed, 580 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..7782bda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/fastapi-limiter-0.1.5.tar.gz
diff --git a/python-fastapi-limiter.spec b/python-fastapi-limiter.spec
new file mode 100644
index 0000000..5343b62
--- /dev/null
+++ b/python-fastapi-limiter.spec
@@ -0,0 +1,578 @@
+%global _empty_manifest_terminate_build 0
+Name: python-fastapi-limiter
+Version: 0.1.5
+Release: 1
+Summary: A request rate limiter for fastapi
+License: Apache2.0
+URL: https://github.com/long2ice/fastapi-limiter
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/19/8a/fd3d43632cb8e009c5ec8cda84e9d213f5c484cd14de99ecbabdc173c935/fastapi-limiter-0.1.5.tar.gz
+BuildArch: noarch
+
+Requires: python3-fastapi
+Requires: python3-redis
+
+%description
+# fastapi-limiter
+
+[![pypi](https://img.shields.io/pypi/v/fastapi-limiter.svg?style=flat)](https://pypi.python.org/pypi/fastapi-limiter)
+[![license](https://img.shields.io/github/license/long2ice/fastapi-limiter)](https://github.com/long2ice/fastapi-limiter/blob/master/LICENCE)
+[![workflows](https://github.com/long2ice/fastapi-limiter/workflows/pypi/badge.svg)](https://github.com/long2ice/fastapi-limiter/actions?query=workflow:pypi)
+[![workflows](https://github.com/long2ice/fastapi-limiter/workflows/ci/badge.svg)](https://github.com/long2ice/fastapi-limiter/actions?query=workflow:ci)
+
+## Introduction
+
+FastAPI-Limiter is a rate limiting tool for [fastapi](https://github.com/tiangolo/fastapi) routes with lua script.
+
+## Requirements
+
+- [redis](https://redis.io/)
+
+## Install
+
+Just install from pypi
+
+```shell script
+> pip install fastapi-limiter
+```
+
+## Quick Start
+
+FastAPI-Limiter is simple to use, which just provide a dependency `RateLimiter`, the following example allow `2` times
+request per `5` seconds in route `/`.
+
+```py
+import redis.asyncio as redis
+import uvicorn
+from fastapi import Depends, FastAPI
+
+from fastapi_limiter import FastAPILimiter
+from fastapi_limiter.depends import RateLimiter
+
+app = FastAPI()
+
+
+@app.on_event("startup")
+async def startup():
+ redis = redis.from_url("redis://localhost", encoding="utf-8", decode_responses=True)
+ await FastAPILimiter.init(redis)
+
+
+@app.get("/", dependencies=[Depends(RateLimiter(times=2, seconds=5))])
+async def index():
+ return {"msg": "Hello World"}
+
+
+if __name__ == "__main__":
+ uvicorn.run("main:app", debug=True, reload=True)
+```
+
+## Usage
+
+There are some config in `FastAPILimiter.init`.
+
+### redis
+
+The `redis` instance of `aioredis`.
+
+### prefix
+
+Prefix of redis key.
+
+### identifier
+
+Identifier of route limit, default is `ip`, you can override it such as `userid` and so on.
+
+```py
+async def default_identifier(request: Request):
+ forwarded = request.headers.get("X-Forwarded-For")
+ if forwarded:
+ return forwarded.split(",")[0]
+ return request.client.host + ":" + request.scope["path"]
+```
+
+### callback
+
+Callback when access is forbidden, default is raise `HTTPException` with `429` status code.
+
+```py
+async def default_callback(request: Request, response: Response, pexpire: int):
+ """
+ default callback when too many requests
+ :param request:
+ :param pexpire: The remaining milliseconds
+ :param response:
+ :return:
+ """
+ expire = ceil(pexpire / 1000)
+
+ raise HTTPException(
+ HTTP_429_TOO_MANY_REQUESTS, "Too Many Requests", headers={"Retry-After": str(expire)}
+ )
+```
+
+## Multiple limiters
+
+You can use multiple limiters in one route.
+
+```py
+@app.get(
+ "/multiple",
+ dependencies=[
+ Depends(RateLimiter(times=1, seconds=5)),
+ Depends(RateLimiter(times=2, seconds=15)),
+ ],
+)
+async def multiple():
+ return {"msg": "Hello World"}
+```
+
+Not that you should note the dependencies orders, keep lower of result of `seconds/times` at the first.
+
+## Rate limiting within a websocket.
+
+While the above examples work with rest requests, FastAPI also allows easy usage
+of websockets, which require a slightly different approach.
+
+Because websockets are likely to be long lived, you may want to rate limit in
+response to data sent over the socket.
+
+You can do this by rate limiting within the body of the websocket handler:
+
+```py
+@app.websocket("/ws")
+async def websocket_endpoint(websocket: WebSocket):
+ await websocket.accept()
+ ratelimit = WebSocketRateLimiter(times=1, seconds=5)
+ while True:
+ try:
+ data = await websocket.receive_text()
+ await ratelimit(websocket, context_key=data) # NB: context_key is optional
+ await websocket.send_text(f"Hello, world")
+ except WebSocketRateLimitException: # Thrown when rate limit exceeded.
+ await websocket.send_text(f"Hello again")
+```
+
+## Lua script
+
+The lua script used.
+
+```lua
+local key = KEYS[1]
+local limit = tonumber(ARGV[1])
+local expire_time = ARGV[2]
+
+local current = tonumber(redis.call('get', key) or "0")
+if current > 0 then
+ if current + 1 > limit then
+ return redis.call("PTTL", key)
+ else
+ redis.call("INCR", key)
+ return 0
+ end
+else
+ redis.call("SET", key, 1, "px", expire_time)
+ return 0
+end
+```
+
+## License
+
+This project is licensed under the
+[Apache-2.0](https://github.com/long2ice/fastapi-limiter/blob/master/LICENCE) License.
+
+
+
+%package -n python3-fastapi-limiter
+Summary: A request rate limiter for fastapi
+Provides: python-fastapi-limiter
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-fastapi-limiter
+# fastapi-limiter
+
+[![pypi](https://img.shields.io/pypi/v/fastapi-limiter.svg?style=flat)](https://pypi.python.org/pypi/fastapi-limiter)
+[![license](https://img.shields.io/github/license/long2ice/fastapi-limiter)](https://github.com/long2ice/fastapi-limiter/blob/master/LICENCE)
+[![workflows](https://github.com/long2ice/fastapi-limiter/workflows/pypi/badge.svg)](https://github.com/long2ice/fastapi-limiter/actions?query=workflow:pypi)
+[![workflows](https://github.com/long2ice/fastapi-limiter/workflows/ci/badge.svg)](https://github.com/long2ice/fastapi-limiter/actions?query=workflow:ci)
+
+## Introduction
+
+FastAPI-Limiter is a rate limiting tool for [fastapi](https://github.com/tiangolo/fastapi) routes with lua script.
+
+## Requirements
+
+- [redis](https://redis.io/)
+
+## Install
+
+Just install from pypi
+
+```shell script
+> pip install fastapi-limiter
+```
+
+## Quick Start
+
+FastAPI-Limiter is simple to use, which just provide a dependency `RateLimiter`, the following example allow `2` times
+request per `5` seconds in route `/`.
+
+```py
+import redis.asyncio as redis
+import uvicorn
+from fastapi import Depends, FastAPI
+
+from fastapi_limiter import FastAPILimiter
+from fastapi_limiter.depends import RateLimiter
+
+app = FastAPI()
+
+
+@app.on_event("startup")
+async def startup():
+ redis = redis.from_url("redis://localhost", encoding="utf-8", decode_responses=True)
+ await FastAPILimiter.init(redis)
+
+
+@app.get("/", dependencies=[Depends(RateLimiter(times=2, seconds=5))])
+async def index():
+ return {"msg": "Hello World"}
+
+
+if __name__ == "__main__":
+ uvicorn.run("main:app", debug=True, reload=True)
+```
+
+## Usage
+
+There are some config in `FastAPILimiter.init`.
+
+### redis
+
+The `redis` instance of `aioredis`.
+
+### prefix
+
+Prefix of redis key.
+
+### identifier
+
+Identifier of route limit, default is `ip`, you can override it such as `userid` and so on.
+
+```py
+async def default_identifier(request: Request):
+ forwarded = request.headers.get("X-Forwarded-For")
+ if forwarded:
+ return forwarded.split(",")[0]
+ return request.client.host + ":" + request.scope["path"]
+```
+
+### callback
+
+Callback when access is forbidden, default is raise `HTTPException` with `429` status code.
+
+```py
+async def default_callback(request: Request, response: Response, pexpire: int):
+ """
+ default callback when too many requests
+ :param request:
+ :param pexpire: The remaining milliseconds
+ :param response:
+ :return:
+ """
+ expire = ceil(pexpire / 1000)
+
+ raise HTTPException(
+ HTTP_429_TOO_MANY_REQUESTS, "Too Many Requests", headers={"Retry-After": str(expire)}
+ )
+```
+
+## Multiple limiters
+
+You can use multiple limiters in one route.
+
+```py
+@app.get(
+ "/multiple",
+ dependencies=[
+ Depends(RateLimiter(times=1, seconds=5)),
+ Depends(RateLimiter(times=2, seconds=15)),
+ ],
+)
+async def multiple():
+ return {"msg": "Hello World"}
+```
+
+Not that you should note the dependencies orders, keep lower of result of `seconds/times` at the first.
+
+## Rate limiting within a websocket.
+
+While the above examples work with rest requests, FastAPI also allows easy usage
+of websockets, which require a slightly different approach.
+
+Because websockets are likely to be long lived, you may want to rate limit in
+response to data sent over the socket.
+
+You can do this by rate limiting within the body of the websocket handler:
+
+```py
+@app.websocket("/ws")
+async def websocket_endpoint(websocket: WebSocket):
+ await websocket.accept()
+ ratelimit = WebSocketRateLimiter(times=1, seconds=5)
+ while True:
+ try:
+ data = await websocket.receive_text()
+ await ratelimit(websocket, context_key=data) # NB: context_key is optional
+ await websocket.send_text(f"Hello, world")
+ except WebSocketRateLimitException: # Thrown when rate limit exceeded.
+ await websocket.send_text(f"Hello again")
+```
+
+## Lua script
+
+The lua script used.
+
+```lua
+local key = KEYS[1]
+local limit = tonumber(ARGV[1])
+local expire_time = ARGV[2]
+
+local current = tonumber(redis.call('get', key) or "0")
+if current > 0 then
+ if current + 1 > limit then
+ return redis.call("PTTL", key)
+ else
+ redis.call("INCR", key)
+ return 0
+ end
+else
+ redis.call("SET", key, 1, "px", expire_time)
+ return 0
+end
+```
+
+## License
+
+This project is licensed under the
+[Apache-2.0](https://github.com/long2ice/fastapi-limiter/blob/master/LICENCE) License.
+
+
+
+%package help
+Summary: Development documents and examples for fastapi-limiter
+Provides: python3-fastapi-limiter-doc
+%description help
+# fastapi-limiter
+
+[![pypi](https://img.shields.io/pypi/v/fastapi-limiter.svg?style=flat)](https://pypi.python.org/pypi/fastapi-limiter)
+[![license](https://img.shields.io/github/license/long2ice/fastapi-limiter)](https://github.com/long2ice/fastapi-limiter/blob/master/LICENCE)
+[![workflows](https://github.com/long2ice/fastapi-limiter/workflows/pypi/badge.svg)](https://github.com/long2ice/fastapi-limiter/actions?query=workflow:pypi)
+[![workflows](https://github.com/long2ice/fastapi-limiter/workflows/ci/badge.svg)](https://github.com/long2ice/fastapi-limiter/actions?query=workflow:ci)
+
+## Introduction
+
+FastAPI-Limiter is a rate limiting tool for [fastapi](https://github.com/tiangolo/fastapi) routes with lua script.
+
+## Requirements
+
+- [redis](https://redis.io/)
+
+## Install
+
+Just install from pypi
+
+```shell script
+> pip install fastapi-limiter
+```
+
+## Quick Start
+
+FastAPI-Limiter is simple to use, which just provide a dependency `RateLimiter`, the following example allow `2` times
+request per `5` seconds in route `/`.
+
+```py
+import redis.asyncio as redis
+import uvicorn
+from fastapi import Depends, FastAPI
+
+from fastapi_limiter import FastAPILimiter
+from fastapi_limiter.depends import RateLimiter
+
+app = FastAPI()
+
+
+@app.on_event("startup")
+async def startup():
+ redis = redis.from_url("redis://localhost", encoding="utf-8", decode_responses=True)
+ await FastAPILimiter.init(redis)
+
+
+@app.get("/", dependencies=[Depends(RateLimiter(times=2, seconds=5))])
+async def index():
+ return {"msg": "Hello World"}
+
+
+if __name__ == "__main__":
+ uvicorn.run("main:app", debug=True, reload=True)
+```
+
+## Usage
+
+There are some config in `FastAPILimiter.init`.
+
+### redis
+
+The `redis` instance of `aioredis`.
+
+### prefix
+
+Prefix of redis key.
+
+### identifier
+
+Identifier of route limit, default is `ip`, you can override it such as `userid` and so on.
+
+```py
+async def default_identifier(request: Request):
+ forwarded = request.headers.get("X-Forwarded-For")
+ if forwarded:
+ return forwarded.split(",")[0]
+ return request.client.host + ":" + request.scope["path"]
+```
+
+### callback
+
+Callback when access is forbidden, default is raise `HTTPException` with `429` status code.
+
+```py
+async def default_callback(request: Request, response: Response, pexpire: int):
+ """
+ default callback when too many requests
+ :param request:
+ :param pexpire: The remaining milliseconds
+ :param response:
+ :return:
+ """
+ expire = ceil(pexpire / 1000)
+
+ raise HTTPException(
+ HTTP_429_TOO_MANY_REQUESTS, "Too Many Requests", headers={"Retry-After": str(expire)}
+ )
+```
+
+## Multiple limiters
+
+You can use multiple limiters in one route.
+
+```py
+@app.get(
+ "/multiple",
+ dependencies=[
+ Depends(RateLimiter(times=1, seconds=5)),
+ Depends(RateLimiter(times=2, seconds=15)),
+ ],
+)
+async def multiple():
+ return {"msg": "Hello World"}
+```
+
+Not that you should note the dependencies orders, keep lower of result of `seconds/times` at the first.
+
+## Rate limiting within a websocket.
+
+While the above examples work with rest requests, FastAPI also allows easy usage
+of websockets, which require a slightly different approach.
+
+Because websockets are likely to be long lived, you may want to rate limit in
+response to data sent over the socket.
+
+You can do this by rate limiting within the body of the websocket handler:
+
+```py
+@app.websocket("/ws")
+async def websocket_endpoint(websocket: WebSocket):
+ await websocket.accept()
+ ratelimit = WebSocketRateLimiter(times=1, seconds=5)
+ while True:
+ try:
+ data = await websocket.receive_text()
+ await ratelimit(websocket, context_key=data) # NB: context_key is optional
+ await websocket.send_text(f"Hello, world")
+ except WebSocketRateLimitException: # Thrown when rate limit exceeded.
+ await websocket.send_text(f"Hello again")
+```
+
+## Lua script
+
+The lua script used.
+
+```lua
+local key = KEYS[1]
+local limit = tonumber(ARGV[1])
+local expire_time = ARGV[2]
+
+local current = tonumber(redis.call('get', key) or "0")
+if current > 0 then
+ if current + 1 > limit then
+ return redis.call("PTTL", key)
+ else
+ redis.call("INCR", key)
+ return 0
+ end
+else
+ redis.call("SET", key, 1, "px", expire_time)
+ return 0
+end
+```
+
+## License
+
+This project is licensed under the
+[Apache-2.0](https://github.com/long2ice/fastapi-limiter/blob/master/LICENCE) License.
+
+
+
+%prep
+%autosetup -n fastapi-limiter-0.1.5
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-fastapi-limiter -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Mon May 15 2023 Python_Bot <Python_Bot@openeuler.org> - 0.1.5-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..1105d3c
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+bdbbc849d1c6fb665b46bc1fc31f51ff fastapi-limiter-0.1.5.tar.gz