add basic rate limiting

This commit is contained in:
2025-07-01 11:38:38 -04:00
parent 1991e5b31b
commit c3f753a4f0
9 changed files with 64 additions and 20 deletions

View File

@ -26,7 +26,13 @@ app = FastAPI(
constants = importlib.import_module("constants").Constants()
util = importlib.import_module("util").Utilities(app, constants)
origins = ["https://codey.lol", "https://old.codey.lol", "https://api.codey.lol", "https://_new.codey.lol", "http://localhost:4321"]
origins = [
"https://codey.lol",
"https://old.codey.lol",
"https://api.codey.lol",
"https://_new.codey.lol",
"http://localhost:4321",
]
app.add_middleware(
CORSMiddleware, # type: ignore

View File

@ -2,7 +2,8 @@ import importlib
import logging
import traceback
from typing import Optional, Union
from fastapi import FastAPI
from fastapi import FastAPI, Depends
from fastapi_throttle import RateLimiter
from fastapi.responses import JSONResponse
from .constructors import (
ValidArtistSearchRequest,
@ -32,7 +33,9 @@ class LastFM(FastAPI):
for endpoint, handler in self.endpoints.items():
app.add_api_route(
f"/{endpoint}", handler, methods=["POST"], include_in_schema=True
f"/{endpoint}", handler,
methods=["POST"], include_in_schema=True,
dependencies=[Depends(RateLimiter(times=2, seconds=2))]
)
async def artist_by_name_handler(

View File

@ -3,7 +3,8 @@ import os
import urllib.parse
import regex
import aiosqlite as sqlite3
from fastapi import FastAPI, HTTPException
from fastapi import FastAPI, HTTPException, Depends
from fastapi_throttle import RateLimiter
from fastapi.responses import JSONResponse
from typing import LiteralString, Optional, Union, Iterable
from regex import Pattern
@ -76,6 +77,7 @@ class LyricSearch(FastAPI):
handler,
methods=["POST"],
include_in_schema=_schema_include,
dependencies=[Depends(RateLimiter(times=2, seconds=3))]
)
async def typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse:

View File

@ -1,5 +1,10 @@
import logging
from fastapi import FastAPI, Request, Response
from fastapi import (
FastAPI,
Request,
Response,
Depends)
from fastapi_throttle import RateLimiter
from fastapi.responses import JSONResponse
from utils.meme_util import MemeUtil
@ -22,7 +27,11 @@ class Meme(FastAPI):
for endpoint, handler in self.endpoints.items():
app.add_api_route(
f"/{endpoint}", handler, methods=["GET"], include_in_schema=True
f"/{endpoint}", handler,
methods=["GET"], include_in_schema=True,
dependencies=[Depends(
RateLimiter(times=2, seconds=2)
)]
)
async def get_meme_by_id(self, id: int, request: Request) -> Response:

View File

@ -4,7 +4,8 @@ import os
import json
import random
from typing import Optional, Annotated
from fastapi import FastAPI, Request, UploadFile, Response, HTTPException, Form
from fastapi import FastAPI, Request, UploadFile, Response, HTTPException, Form, Depends
from fastapi_throttle import RateLimiter
from fastapi.responses import JSONResponse
import redis.asyncio as redis
from lyric_search.sources import private, cache as LyricsCache, redis_cache
@ -40,11 +41,16 @@ class Misc(FastAPI):
for endpoint, handler in self.endpoints.items():
app.add_api_route(
f"/{endpoint}", handler, methods=["GET"], include_in_schema=True
f"/{endpoint}",
handler,
methods=["GET"],
include_in_schema=True,
dependencies=[Depends(RateLimiter(times=2, seconds=5))],
)
app.add_api_route(
"/misc/upload_activity_image", self.upload_activity_image, methods=["POST"]
"/misc/upload_activity_image", self.upload_activity_image, methods=["POST"],
dependencies=[Depends(RateLimiter(times=2, seconds=5))],
)
logging.debug("Loading NaaS reasons")
@ -66,6 +72,7 @@ class Misc(FastAPI):
except Exception as e:
logging.debug("Exception: %s", str(e))
return "No."
async def no(self) -> JSONResponse:
"""NaaS"""

View File

@ -13,8 +13,14 @@ from .constructors import (
)
from utils import radio_util
from typing import Optional
from fastapi import FastAPI, BackgroundTasks, Request, Response, HTTPException
from starlette.concurrency import run_in_threadpool
from fastapi import (
FastAPI,
BackgroundTasks,
Request,
Response,
HTTPException,
Depends)
from fastapi_throttle import RateLimiter
from fastapi.responses import RedirectResponse, JSONResponse
@ -43,7 +49,8 @@ class Radio(FastAPI):
for endpoint, handler in self.endpoints.items():
app.add_api_route(
f"/{endpoint}", handler, methods=["POST"], include_in_schema=True
f"/{endpoint}", handler, methods=["POST"], include_in_schema=True,
dependencies=[Depends(RateLimiter(times=10, seconds=5))],
)
# NOTE: Not in loop because method is GET for this endpoint
@ -58,7 +65,7 @@ class Radio(FastAPI):
async def on_start(self) -> None:
logging.info("radio: Initializing")
await run_in_threadpool(self.radio_util.load_playlist)
self.loop.run_in_executor(None, self.radio_util.load_playlist)
async def radio_skip(
self, data: ValidRadioNextRequest, request: Request
@ -317,7 +324,7 @@ class Radio(FastAPI):
if len(self.radio_util.active_playlist) > 1:
self.radio_util.active_playlist.append(next) # Push to end of playlist
else:
await run_in_threadpool(self.radio_util.load_playlist)
self.loop.run_in_executor(None, self.radio_util.load_playlist)
self.radio_util.now_playing = next
next["start"] = time_started

View File

@ -2,7 +2,8 @@ import os
import random
from typing import LiteralString, Optional, Union
import aiosqlite as sqlite3
from fastapi import FastAPI
from fastapi import FastAPI, Depends
from fastapi_throttle import RateLimiter
from fastapi.responses import JSONResponse
from .constructors import RandMsgRequest
@ -19,7 +20,10 @@ class RandMsg(FastAPI):
self.endpoint_name = "randmsg"
app.add_api_route(
f"/{self.endpoint_name}", self.randmsg_handler, methods=["POST"]
f"/{self.endpoint_name}", self.randmsg_handler,
methods=["POST"], dependencies=[Depends(
RateLimiter(times=5, seconds=2)
)]
)
async def randmsg_handler(

View File

@ -1,6 +1,7 @@
import os
import aiosqlite as sqlite3
from fastapi import FastAPI
from fastapi import FastAPI, Depends
from fastapi_throttle import RateLimiter
from fastapi.responses import JSONResponse
from typing import Optional, LiteralString, Union
from .constructors import ValidShowEpisodeLineRequest, ValidShowEpisodeListRequest
@ -24,7 +25,9 @@ class Transcriptions(FastAPI):
for endpoint, handler in self.endpoints.items():
app.add_api_route(
f"/{endpoint}", handler, methods=["POST"], include_in_schema=True
f"/{endpoint}", handler,
methods=["POST"], include_in_schema=True,
dependencies=[Depends(RateLimiter(times=2, seconds=2))]
)
async def get_episodes_handler(

View File

@ -1,6 +1,7 @@
import importlib
from fastapi import FastAPI
from fastapi import FastAPI, Depends
from fastapi.responses import JSONResponse
from fastapi_throttle import RateLimiter
from typing import Optional, Union
from .constructors import ValidYTSearchRequest
@ -22,7 +23,9 @@ class YT(FastAPI):
for endpoint, handler in self.endpoints.items():
app.add_api_route(
f"/{endpoint}", handler, methods=["POST"], include_in_schema=True
f"/{endpoint}", handler,
methods=["POST"], include_in_schema=True,
dependencies=[Depends(RateLimiter(times=2, seconds=2))]
)
async def yt_video_search_handler(self, data: ValidYTSearchRequest) -> JSONResponse: