fix(upload): configure chat attachment size limit (#2439)

This commit is contained in:
nubs
2026-06-07 20:42:24 +00:00
committed by GitHub
parent 8746c9c0df
commit 865e61450e
9 changed files with 106 additions and 4 deletions
+5 -2
View File
@@ -13,6 +13,8 @@ from fastapi import HTTPException
from fastapi import UploadFile
from typing import List, Optional
from src.upload_limits import format_byte_limit, get_chat_upload_max_bytes
logger = logging.getLogger(__name__)
@@ -201,12 +203,13 @@ def validate_file_upload(file: UploadFile) -> UploadFile:
}
)
if file_size > 10 * 1024 * 1024:
upload_limit = get_chat_upload_max_bytes()
if file_size > upload_limit:
raise HTTPException(
status_code=400,
detail={
"error": "FILE_TOO_LARGE",
"message": "File size exceeds 10MB limit"
"message": f"File size exceeds {format_byte_limit(upload_limit)} limit"
}
)
except IOError as e:
+6 -2
View File
@@ -12,6 +12,10 @@ import threading
from datetime import datetime, timedelta
from typing import Dict, Any, Optional
from fastapi import HTTPException, UploadFile
from src.upload_limits import format_byte_limit, get_chat_upload_max_bytes
def secure_filename(filename: str) -> str:
"""Sanitize a filename (replaces werkzeug.utils.secure_filename)."""
import unicodedata
@@ -73,7 +77,7 @@ class UploadHandler:
def __init__(self, base_dir: str, upload_dir: str):
self.base_dir = base_dir
self.upload_dir = upload_dir
self.max_upload_size = 10 * 1024 * 1024 # 10MB
self.max_upload_size = get_chat_upload_max_bytes()
self.max_concurrent_uploads = 3
self.cleanup_days = 30
# Per-IP per-minute cap. save_upload() counts EACH file, and the chat
@@ -518,7 +522,7 @@ class UploadHandler:
if file_size > self.max_upload_size:
raise HTTPException(
status_code=400,
detail=f"File size exceeds {self.max_upload_size/1024/1024}MB limit"
detail=f"File size exceeds {format_byte_limit(self.max_upload_size)} limit"
)
# Get original filename and sanitize it
+22
View File
@@ -1,7 +1,12 @@
"""Small helpers for route-local upload size caps."""
import os
from fastapi import HTTPException, UploadFile
DEFAULT_CHAT_UPLOAD_MAX_BYTES = 10 * 1024 * 1024
CHAT_UPLOAD_MAX_BYTES_ENV = "ODYSSEUS_CHAT_UPLOAD_MAX_BYTES"
def format_byte_limit(limit: int) -> str:
if limit % (1024 * 1024) == 0:
@@ -11,6 +16,23 @@ def format_byte_limit(limit: int) -> str:
return f"{limit} bytes"
def read_byte_limit_env(name: str, default: int) -> int:
raw = os.getenv(name)
if raw is None or not raw.strip():
return default
try:
limit = int(raw)
except ValueError as exc:
raise ValueError(f"{name} must be an integer byte count") from exc
if limit < 1:
raise ValueError(f"{name} must be greater than 0")
return limit
def get_chat_upload_max_bytes() -> int:
return read_byte_limit_env(CHAT_UPLOAD_MAX_BYTES_ENV, DEFAULT_CHAT_UPLOAD_MAX_BYTES)
async def read_upload_limited(upload: UploadFile, limit: int, label: str = "Upload") -> bytes:
"""Read an UploadFile with a hard byte cap."""
data = await upload.read(limit + 1)