From aaabe1b8c4e07a2f6667fc8ff75157494ff5ff16 Mon Sep 17 00:00:00 2001 From: MrWaradana Date: Mon, 2 Mar 2026 16:25:57 +0700 Subject: [PATCH] fix middleware --- src/middleware.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/middleware.py b/src/middleware.py index f428ef5..65c9aa3 100644 --- a/src/middleware.py +++ b/src/middleware.py @@ -193,27 +193,35 @@ class RequestValidationMiddleware(BaseHTTPMiddleware): ) # ------------------------- - # 4. Single source enforcement + # 4. JSON body inspection & Single source enforcement # Ensuring data comes from ONLY one source (Query OR Body). # ------------------------- content_type = request.headers.get("content-type", "") - has_json_body = content_type.startswith("application/json") + has_json_header = content_type.startswith("application/json") + # Read body now so we can check if it's actually empty + body = b"" + if has_json_header: + body = await request.body() + + # We consider it a "JSON body" source ONLY if it's not empty and not just "{}" + has_actual_json_body = has_json_header and body and body.strip() != b"{}" + # Check for data parameters in query (anything whitelisted as 'data' but not 'session/auth') data_params_in_query = [ key for key, _ in params if key in ALLOWED_QUERY_PARAMS and key not in WRITE_METHOD_ALLOWED_PARAMS ] - if has_json_body: - # If sending JSON body, we forbid any data in query string (one source only) + if has_actual_json_body: + # If sending actual JSON body, we forbid any data in query string (one source only) if data_params_in_query: raise HTTPException( status_code=422, detail=f"Single source enforcement: Data received from both JSON body and query string ({data_params_in_query}). Use only one source.", ) - # Special case: GET with body is discouraged/forbidden in many strict security contexts + # Special case: GET with actual body is discouraged/forbidden if request.method == "GET": raise HTTPException( status_code=422, @@ -265,17 +273,9 @@ class RequestValidationMiddleware(BaseHTTPMiddleware): ) # ------------------------- - # 7. JSON body inspection + # 7. JSON body inspection & Re-injection # ------------------------- - if content_type.startswith("application/json"): - body = await request.body() - - #if len(body) > MAX_JSON_BODY_SIZE: - # raise HTTPException( - # status_code=413, - # detail="JSON body too large", - # ) - + if has_json_header: if body: try: payload = json.loads(body) @@ -284,13 +284,11 @@ class RequestValidationMiddleware(BaseHTTPMiddleware): status_code=422, detail="Invalid JSON body", ) - inspect_json(payload) # Re-inject body for downstream handlers async def receive(): return {"type": "http.request", "body": body} - request._receive = receive # noqa: protected-access return await call_next(request)