fix(server): return JSON-RPC -32700 on non-JSON request body
CI / lint (pull_request) Successful in 45s
CI / helm (pull_request) Successful in 30s
CI / typecheck (pull_request) Successful in 1m2s
CI / quality (pull_request) Successful in 1m7s
CI / build (pull_request) Successful in 56s
CI / security (pull_request) Successful in 1m13s
CI / push-validation (pull_request) Successful in 27s
CI / integration_tests (pull_request) Successful in 3m1s
CI / unit_tests (pull_request) Failing after 6m17s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
CI / lint (pull_request) Successful in 45s
CI / helm (pull_request) Successful in 30s
CI / typecheck (pull_request) Successful in 1m2s
CI / quality (pull_request) Successful in 1m7s
CI / build (pull_request) Successful in 56s
CI / security (pull_request) Successful in 1m13s
CI / push-validation (pull_request) Successful in 27s
CI / integration_tests (pull_request) Successful in 3m1s
CI / unit_tests (pull_request) Failing after 6m17s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
Wrap `await request.json()` in its own try-except for `json.JSONDecodeError` so malformed/non-JSON request bodies yield HTTP 400 with JSON-RPC error code -32700 (Parse error) instead of propagating unhandled to FastAPI's ServerErrorMiddleware and returning HTTP 500. Update the BDD step `step_post_a2a_malformed` to send actual raw non-JSON bytes (`content=b"not-valid-json"`) so the scenario exercises the JSON parse failure path rather than the existing A2aRequest validation path (-32600). ISSUES CLOSED: #863
This commit is contained in:
@@ -132,8 +132,11 @@ def step_post_a2a(context: Any, operation: str) -> None:
|
||||
|
||||
@when("I POST a malformed JSON body to /a2a")
|
||||
def step_post_a2a_malformed(context: Any) -> None:
|
||||
# Send a body that cannot be parsed into A2aRequest (missing operation)
|
||||
context.response = context.test_client.post("/a2a", json={"bad": "data"})
|
||||
context.response = context.test_client.post(
|
||||
"/a2a",
|
||||
content=b"not-valid-json",
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
|
||||
|
||||
@then("the response status code should be {code:d}")
|
||||
|
||||
@@ -13,6 +13,7 @@ at ``/.well-known/agent.json`` per the A2A specification.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
import structlog
|
||||
@@ -120,7 +121,20 @@ def create_asgi_app(
|
||||
schema, dispatches it through the facade, and returns the
|
||||
:class:`A2aResponse` envelope.
|
||||
"""
|
||||
body: dict[str, Any] = await request.json()
|
||||
try:
|
||||
body: dict[str, Any] = await request.json()
|
||||
except json.JSONDecodeError as exc:
|
||||
logger.warning("a2a.server.parse_error", error=str(exc))
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={
|
||||
"jsonrpc": "2.0",
|
||||
"error": {
|
||||
"code": -32700,
|
||||
"message": "Parse error: request body is not valid JSON",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
# Accept "operation" as an alias for "method" (proprietary wire format).
|
||||
if "method" not in body and "operation" in body:
|
||||
|
||||
Reference in New Issue
Block a user