削除にレートリミットを掛ける
This commit is contained in:
parent
36ba71c839
commit
394babfff8
3 changed files with 32 additions and 8 deletions
|
@ -20,6 +20,14 @@ docker run --detach \
|
||||||
mongo
|
mongo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --detach \
|
||||||
|
--name litey-redis-debug \
|
||||||
|
--volume litey-redis-debug:/data/db \
|
||||||
|
--publish 6379:6379 \
|
||||||
|
redis
|
||||||
|
```
|
||||||
|
|
||||||
サーバーを起動します
|
サーバーを起動します
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
31
app.py
31
app.py
|
@ -7,15 +7,17 @@ from urllib.parse import urlparse
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from re import escape, compile, IGNORECASE
|
from re import escape, compile, IGNORECASE
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from random import randint
|
|
||||||
|
|
||||||
from requests import get
|
from requests import get
|
||||||
from fastapi import FastAPI, Request, Response, status
|
from fastapi import FastAPI, Request, Response, status, Depends
|
||||||
from fastapi.responses import JSONResponse, Response, PlainTextResponse, FileResponse
|
from fastapi.responses import JSONResponse, Response, PlainTextResponse, FileResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from pymongo import MongoClient, DESCENDING
|
from pymongo import MongoClient, DESCENDING
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from redis.asyncio import from_url
|
||||||
|
from fastapi_limiter import FastAPILimiter
|
||||||
|
from fastapi_limiter.depends import RateLimiter
|
||||||
|
|
||||||
# Jinja2
|
# Jinja2
|
||||||
|
|
||||||
|
@ -50,6 +52,17 @@ def is_over_n_hours(src: datetime, hours: int) -> bool:
|
||||||
|
|
||||||
ctx = {}
|
ctx = {}
|
||||||
|
|
||||||
|
async def default_identifier(req: Request):
|
||||||
|
cloudflare_ip = req.headers.get("CF-Connecting-IP")
|
||||||
|
if cloudflare_ip:
|
||||||
|
return cloudflare_ip.split(",")[0]
|
||||||
|
|
||||||
|
forwarded = req.headers.get("X-Forwarded-For")
|
||||||
|
if forwarded:
|
||||||
|
return forwarded.split(",")[0]
|
||||||
|
|
||||||
|
return req.client.host + ":" + req.scope["path"]
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
ctx["templates"] = Jinja2Templates("templates")
|
ctx["templates"] = Jinja2Templates("templates")
|
||||||
|
@ -71,11 +84,17 @@ async def lifespan(app: FastAPI):
|
||||||
ctx["mongo_client"].litey.ngs.create_index("word", unique=True)
|
ctx["mongo_client"].litey.ngs.create_index("word", unique=True)
|
||||||
|
|
||||||
pprint(ctx)
|
pprint(ctx)
|
||||||
|
|
||||||
|
redis_uri = environ.get("REDIS_URI", "redis://127.0.0.1:6379/")
|
||||||
|
redis_connection = from_url(redis_uri, encoding="utf8")
|
||||||
|
await FastAPILimiter.init(redis_connection, identifier=default_identifier)
|
||||||
yield
|
yield
|
||||||
ctx["mongo_client"].close()
|
ctx["mongo_client"].close()
|
||||||
|
|
||||||
ctx.clear()
|
ctx.clear()
|
||||||
|
|
||||||
|
await FastAPILimiter.close()
|
||||||
|
|
||||||
# スニペット
|
# スニペット
|
||||||
|
|
||||||
class LiteYItem(BaseModel):
|
class LiteYItem(BaseModel):
|
||||||
|
@ -112,7 +131,7 @@ def fastapi_serve(dir: str, ref: str, indexes: List[str] = ["index.html", "index
|
||||||
return FileResponse(path)
|
return FileResponse(path)
|
||||||
|
|
||||||
def get_ip(req: Request) -> str:
|
def get_ip(req: Request) -> str:
|
||||||
return req.headers.get("CF-Connecting-IP") or req.client.host
|
return req.headers.get("CF-Connecting-IP") or req.headers.get("X-Forwarded-For") or req.client.host
|
||||||
|
|
||||||
def get_litey_notes(id: str = None) -> List[dict]:
|
def get_litey_notes(id: str = None) -> List[dict]:
|
||||||
if not id:
|
if not id:
|
||||||
|
@ -162,12 +181,8 @@ async def api_post(item: LiteYItem, req: Request):
|
||||||
|
|
||||||
return PlainTextResponse("OK")
|
return PlainTextResponse("OK")
|
||||||
|
|
||||||
@app.post("/api/litey/delete")
|
@app.post("/api/litey/delete", dependencies=[Depends(RateLimiter(times=1, seconds=86400))])
|
||||||
async def api_delete(item: LiteYDeleteItem):
|
async def api_delete(item: LiteYDeleteItem):
|
||||||
rand = randint(1, 100)
|
|
||||||
if rand != 100:
|
|
||||||
return PlainTextResponse(f"{rand} は 100 ではありません。", 403)
|
|
||||||
|
|
||||||
ctx["mongo_client"].litey.notes.delete_one({
|
ctx["mongo_client"].litey.notes.delete_one({
|
||||||
"id": item.id
|
"id": item.id
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,3 +2,4 @@ requests==2.32.3
|
||||||
fastapi[standard]==0.115.7
|
fastapi[standard]==0.115.7
|
||||||
pymongo==4.10.1
|
pymongo==4.10.1
|
||||||
Jinja2==3.1.5
|
Jinja2==3.1.5
|
||||||
|
fastapi-limiter==0.1.6
|
||||||
|
|
Loading…
Add table
Reference in a new issue