add basic rate limiting
This commit is contained in:
8
base.py
8
base.py
@ -26,7 +26,13 @@ app = FastAPI(
|
|||||||
constants = importlib.import_module("constants").Constants()
|
constants = importlib.import_module("constants").Constants()
|
||||||
util = importlib.import_module("util").Utilities(app, 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(
|
app.add_middleware(
|
||||||
CORSMiddleware, # type: ignore
|
CORSMiddleware, # type: ignore
|
||||||
|
@ -2,7 +2,8 @@ import importlib
|
|||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Optional, Union
|
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 fastapi.responses import JSONResponse
|
||||||
from .constructors import (
|
from .constructors import (
|
||||||
ValidArtistSearchRequest,
|
ValidArtistSearchRequest,
|
||||||
@ -32,7 +33,9 @@ class LastFM(FastAPI):
|
|||||||
|
|
||||||
for endpoint, handler in self.endpoints.items():
|
for endpoint, handler in self.endpoints.items():
|
||||||
app.add_api_route(
|
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(
|
async def artist_by_name_handler(
|
||||||
|
@ -3,7 +3,8 @@ import os
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
import regex
|
import regex
|
||||||
import aiosqlite as sqlite3
|
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 fastapi.responses import JSONResponse
|
||||||
from typing import LiteralString, Optional, Union, Iterable
|
from typing import LiteralString, Optional, Union, Iterable
|
||||||
from regex import Pattern
|
from regex import Pattern
|
||||||
@ -76,6 +77,7 @@ class LyricSearch(FastAPI):
|
|||||||
handler,
|
handler,
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
include_in_schema=_schema_include,
|
include_in_schema=_schema_include,
|
||||||
|
dependencies=[Depends(RateLimiter(times=2, seconds=3))]
|
||||||
)
|
)
|
||||||
|
|
||||||
async def typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse:
|
async def typeahead_handler(self, data: ValidTypeAheadRequest) -> JSONResponse:
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import logging
|
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 fastapi.responses import JSONResponse
|
||||||
from utils.meme_util import MemeUtil
|
from utils.meme_util import MemeUtil
|
||||||
|
|
||||||
@ -22,7 +27,11 @@ class Meme(FastAPI):
|
|||||||
|
|
||||||
for endpoint, handler in self.endpoints.items():
|
for endpoint, handler in self.endpoints.items():
|
||||||
app.add_api_route(
|
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:
|
async def get_meme_by_id(self, id: int, request: Request) -> Response:
|
||||||
|
@ -4,7 +4,8 @@ import os
|
|||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
from typing import Optional, Annotated
|
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
|
from fastapi.responses import JSONResponse
|
||||||
import redis.asyncio as redis
|
import redis.asyncio as redis
|
||||||
from lyric_search.sources import private, cache as LyricsCache, redis_cache
|
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():
|
for endpoint, handler in self.endpoints.items():
|
||||||
app.add_api_route(
|
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(
|
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")
|
logging.debug("Loading NaaS reasons")
|
||||||
@ -66,6 +72,7 @@ class Misc(FastAPI):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.debug("Exception: %s", str(e))
|
logging.debug("Exception: %s", str(e))
|
||||||
return "No."
|
return "No."
|
||||||
|
|
||||||
|
|
||||||
async def no(self) -> JSONResponse:
|
async def no(self) -> JSONResponse:
|
||||||
"""NaaS"""
|
"""NaaS"""
|
||||||
|
@ -13,8 +13,14 @@ from .constructors import (
|
|||||||
)
|
)
|
||||||
from utils import radio_util
|
from utils import radio_util
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from fastapi import FastAPI, BackgroundTasks, Request, Response, HTTPException
|
from fastapi import (
|
||||||
from starlette.concurrency import run_in_threadpool
|
FastAPI,
|
||||||
|
BackgroundTasks,
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
HTTPException,
|
||||||
|
Depends)
|
||||||
|
from fastapi_throttle import RateLimiter
|
||||||
from fastapi.responses import RedirectResponse, JSONResponse
|
from fastapi.responses import RedirectResponse, JSONResponse
|
||||||
|
|
||||||
|
|
||||||
@ -43,7 +49,8 @@ class Radio(FastAPI):
|
|||||||
|
|
||||||
for endpoint, handler in self.endpoints.items():
|
for endpoint, handler in self.endpoints.items():
|
||||||
app.add_api_route(
|
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
|
# NOTE: Not in loop because method is GET for this endpoint
|
||||||
@ -58,7 +65,7 @@ class Radio(FastAPI):
|
|||||||
|
|
||||||
async def on_start(self) -> None:
|
async def on_start(self) -> None:
|
||||||
logging.info("radio: Initializing")
|
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(
|
async def radio_skip(
|
||||||
self, data: ValidRadioNextRequest, request: Request
|
self, data: ValidRadioNextRequest, request: Request
|
||||||
@ -317,7 +324,7 @@ class Radio(FastAPI):
|
|||||||
if len(self.radio_util.active_playlist) > 1:
|
if len(self.radio_util.active_playlist) > 1:
|
||||||
self.radio_util.active_playlist.append(next) # Push to end of playlist
|
self.radio_util.active_playlist.append(next) # Push to end of playlist
|
||||||
else:
|
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
|
self.radio_util.now_playing = next
|
||||||
next["start"] = time_started
|
next["start"] = time_started
|
||||||
|
@ -2,7 +2,8 @@ import os
|
|||||||
import random
|
import random
|
||||||
from typing import LiteralString, Optional, Union
|
from typing import LiteralString, Optional, Union
|
||||||
import aiosqlite as sqlite3
|
import aiosqlite as sqlite3
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Depends
|
||||||
|
from fastapi_throttle import RateLimiter
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from .constructors import RandMsgRequest
|
from .constructors import RandMsgRequest
|
||||||
|
|
||||||
@ -19,7 +20,10 @@ class RandMsg(FastAPI):
|
|||||||
self.endpoint_name = "randmsg"
|
self.endpoint_name = "randmsg"
|
||||||
|
|
||||||
app.add_api_route(
|
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(
|
async def randmsg_handler(
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import aiosqlite as sqlite3
|
import aiosqlite as sqlite3
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Depends
|
||||||
|
from fastapi_throttle import RateLimiter
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from typing import Optional, LiteralString, Union
|
from typing import Optional, LiteralString, Union
|
||||||
from .constructors import ValidShowEpisodeLineRequest, ValidShowEpisodeListRequest
|
from .constructors import ValidShowEpisodeLineRequest, ValidShowEpisodeListRequest
|
||||||
@ -24,7 +25,9 @@ class Transcriptions(FastAPI):
|
|||||||
|
|
||||||
for endpoint, handler in self.endpoints.items():
|
for endpoint, handler in self.endpoints.items():
|
||||||
app.add_api_route(
|
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(
|
async def get_episodes_handler(
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import importlib
|
import importlib
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI, Depends
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
from fastapi_throttle import RateLimiter
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
from .constructors import ValidYTSearchRequest
|
from .constructors import ValidYTSearchRequest
|
||||||
|
|
||||||
@ -22,7 +23,9 @@ class YT(FastAPI):
|
|||||||
|
|
||||||
for endpoint, handler in self.endpoints.items():
|
for endpoint, handler in self.endpoints.items():
|
||||||
app.add_api_route(
|
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:
|
async def yt_video_search_handler(self, data: ValidYTSearchRequest) -> JSONResponse:
|
||||||
|
Reference in New Issue
Block a user