From 8df8183a9f19472f0c7baaa7d4cee173ae5dee9a Mon Sep 17 00:00:00 2001 From: ZdenekSrotyr Date: Thu, 9 Apr 2026 07:14:16 +0200 Subject: [PATCH] feat: add 50 MB upload size limit to session and artifact endpoints Rejects files exceeding MAX_UPLOAD_SIZE with HTTP 413 before writing to disk. --- app/api/upload.py | 6 ++++++ tests/test_api_complete.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/app/api/upload.py b/app/api/upload.py index 26003db..f7eb1d7 100644 --- a/app/api/upload.py +++ b/app/api/upload.py @@ -12,6 +12,8 @@ from app.utils import get_data_dir as _get_data_dir router = APIRouter(prefix="/api/upload", tags=["upload"]) +MAX_UPLOAD_SIZE = 50 * 1024 * 1024 # 50 MB + @router.post("/sessions") async def upload_session( @@ -29,6 +31,8 @@ async def upload_session( filename = f"upload_{uuid.uuid4().hex[:8]}" target = sessions_dir / filename content = await file.read() + if len(content) > MAX_UPLOAD_SIZE: + raise HTTPException(status_code=413, detail=f"File too large (max {MAX_UPLOAD_SIZE // 1024 // 1024}MB)") target.write_bytes(content) return {"status": "ok", "path": str(target), "size": len(content)} @@ -49,6 +53,8 @@ async def upload_artifact( filename = f"upload_{uuid.uuid4().hex[:8]}" target = artifacts_dir / filename content = await file.read() + if len(content) > MAX_UPLOAD_SIZE: + raise HTTPException(status_code=413, detail=f"File too large (max {MAX_UPLOAD_SIZE // 1024 // 1024}MB)") target.write_bytes(content) return {"status": "ok", "path": str(target), "size": len(content)} diff --git a/tests/test_api_complete.py b/tests/test_api_complete.py index 04979a3..7937303 100644 --- a/tests/test_api_complete.py +++ b/tests/test_api_complete.py @@ -204,3 +204,17 @@ class TestWebUI: def test_health_no_auth(self, client): resp = client["client"].get("/api/health") assert resp.status_code == 200 + + +# ---- Upload ---- + +class TestUpload: + def test_upload_rejects_oversized_file(self, client): + import io + large_data = b"x" * (50 * 1024 * 1024 + 1) + resp = client["client"].post( + "/api/upload/artifacts", + files={"file": ("big.csv", io.BytesIO(large_data), "text/csv")}, + headers=_h(client["admin"]), + ) + assert resp.status_code == 413