11"""A simple FastAPI app that serves a REST API for proselint."""
22
3+ from os import getenv
4+
35from fastapi import FastAPI , HTTPException , Request , Response , status
46from fastapi .middleware .cors import CORSMiddleware
57from slowapi import Limiter
1113from proselint .registry import CheckRegistry
1214from proselint .tools import LintFile , LintResult
1315
16+ MAX_BODY_BYTES = int (getenv ("MAX_BODY_BYTES" , str (64 * 1024 )))
17+ RATELIMIT = getenv ("RATELIMIT" , "60/minute" )
18+
1419
1520def _lint (input_text : str ) -> list [LintResult ]:
1621 return LintFile (content = input_text , source = "<api>" ).lint ()
@@ -67,7 +72,7 @@ async def health() -> dict[str, str]:
6772
6873
6974@app .post ("/v1" )
70- @limiter .limit ("60/minute" )
75+ @limiter .limit (RATELIMIT )
7176async def index (request : Request ) -> dict [str , object ]:
7277 """Endpoint that lints text using proselint."""
7378 body = await request .body ()
@@ -78,6 +83,12 @@ async def index(request: Request) -> dict[str, object]:
7883 "request body must contain text"
7984 )
8085
86+ if len (body ) > MAX_BODY_BYTES :
87+ raise _error (
88+ status .HTTP_413_REQUEST_ENTITY_TOO_LARGE ,
89+ f"request body must be at most { MAX_BODY_BYTES } bytes"
90+ )
91+
8192 try :
8293 text = body .decode ("utf-8" )
8394 except UnicodeDecodeError :
0 commit comments