From c2b6068238e7167a25d5962d5a7c49d803a2b84a Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 15:03:19 +0000 Subject: [PATCH 1/9] feat: add option to disable oversized payload check in JSONRPC applications --- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 30 ++++++++++++------- src/a2a/server/apps/jsonrpc/starlette_app.py | 4 +++ .../server/apps/jsonrpc/test_serialization.py | 27 +++++++++++++++++ 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index d258916c..e02ba252 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -185,6 +185,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, + disable_content_length_check: bool = False, ) -> None: """Initializes the JSONRPCApplication. @@ -202,6 +203,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. + disable_content_length_check: An optional, if True disables the check + for oversized payloads. """ if not _package_starlette_installed: raise ImportError( @@ -220,6 +223,7 @@ def __init__( # noqa: PLR0913 extended_card_modifier=extended_card_modifier, ) self._context_builder = context_builder or DefaultCallContextBuilder() + self._disable_content_length_check = disable_content_length_check def _generate_error_response( self, request_id: str | int | None, error: JSONRPCError | A2AError @@ -291,18 +295,22 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 request_id, str | int ): request_id = None - # Treat very large payloads as invalid request (-32600) before routing - with contextlib.suppress(Exception): - content_length = int(request.headers.get('content-length', '0')) - if content_length and content_length > MAX_CONTENT_LENGTH: - return self._generate_error_response( - request_id, - A2AError( - root=InvalidRequestError( - message='Payload too large' - ) - ), + # If content lenght check is not diasbled, + # treat very large payloads as invalid request (-32600) before routing + if not self._disable_content_length_check: + with contextlib.suppress(Exception): + content_length = int( + request.headers.get('content-length', '0') ) + if content_length and content_length > MAX_CONTENT_LENGTH: + return self._generate_error_response( + request_id, + A2AError( + root=InvalidRequestError( + message='Payload too large' + ) + ), + ) logger.debug('Request body: %s', body) # 1) Validate base JSON-RPC structure only (-32600 on failure) try: diff --git a/src/a2a/server/apps/jsonrpc/starlette_app.py b/src/a2a/server/apps/jsonrpc/starlette_app.py index b268d043..da8cbff0 100644 --- a/src/a2a/server/apps/jsonrpc/starlette_app.py +++ b/src/a2a/server/apps/jsonrpc/starlette_app.py @@ -59,6 +59,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, + disable_content_length_check: bool = False, ) -> None: """Initializes the A2AStarletteApplication. @@ -76,6 +77,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. + disable_content_length_check: An optional, if True disables the check + for oversized payloads. """ if not _package_starlette_installed: raise ImportError( @@ -90,6 +93,7 @@ def __init__( # noqa: PLR0913 context_builder=context_builder, card_modifier=card_modifier, extended_card_modifier=extended_card_modifier, + disable_content_length_check=disable_content_length_check, ) def routes( diff --git a/tests/server/apps/jsonrpc/test_serialization.py b/tests/server/apps/jsonrpc/test_serialization.py index 9365017b..bd9190a4 100644 --- a/tests/server/apps/jsonrpc/test_serialization.py +++ b/tests/server/apps/jsonrpc/test_serialization.py @@ -6,6 +6,7 @@ from pydantic import ValidationError from starlette.testclient import TestClient +from a2a.server.apps.jsonrpc.jsonrpc_app import MAX_CONTENT_LENGTH from a2a.server.apps import A2AFastAPIApplication, A2AStarletteApplication from a2a.types import ( APIKeySecurityScheme, @@ -136,6 +137,32 @@ def test_handle_oversized_payload(agent_card_with_api_key: AgentCard): assert data['error']['code'] == InvalidRequestError().code +def test_handle_oversized_payload_with_check_disabled( + agent_card_with_api_key: AgentCard, +): + """Test handling of oversized JSON payloads when the check is disabled.""" + handler = mock.AsyncMock() + app_instance = A2AStarletteApplication( + agent_card_with_api_key, handler, disable_content_length_check=True + ) + client = TestClient(app_instance.build()) + + large_string = 'a' * 11 * 1_000_000 # 11MB string + payload = { + 'jsonrpc': '2.0', + 'method': 'test', + 'id': 1, + 'params': {'data': large_string}, + } + + response = client.post('/', json=payload) + assert response.status_code == 200 + data = response.json() + # With the check disabled, it shouldn't return InvalidRequestError due to size. + # It will likely error out deeper in the handler, but not with the size-specific code. + assert data['error']['code'] != InvalidRequestError().code + + def test_handle_unicode_characters(agent_card_with_api_key: AgentCard): """Test handling of unicode characters in JSON payload.""" handler = mock.AsyncMock() From a8aab3ed7351ad6f39ee7502fe2813bbfd830ff2 Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 15:03:19 +0000 Subject: [PATCH 2/9] feat: add option to disable oversized payload check in JSONRPC applications --- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 30 ++++++++++++------- src/a2a/server/apps/jsonrpc/starlette_app.py | 4 +++ .../server/apps/jsonrpc/test_serialization.py | 26 ++++++++++++++++ 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index d258916c..e02ba252 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -185,6 +185,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, + disable_content_length_check: bool = False, ) -> None: """Initializes the JSONRPCApplication. @@ -202,6 +203,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. + disable_content_length_check: An optional, if True disables the check + for oversized payloads. """ if not _package_starlette_installed: raise ImportError( @@ -220,6 +223,7 @@ def __init__( # noqa: PLR0913 extended_card_modifier=extended_card_modifier, ) self._context_builder = context_builder or DefaultCallContextBuilder() + self._disable_content_length_check = disable_content_length_check def _generate_error_response( self, request_id: str | int | None, error: JSONRPCError | A2AError @@ -291,18 +295,22 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 request_id, str | int ): request_id = None - # Treat very large payloads as invalid request (-32600) before routing - with contextlib.suppress(Exception): - content_length = int(request.headers.get('content-length', '0')) - if content_length and content_length > MAX_CONTENT_LENGTH: - return self._generate_error_response( - request_id, - A2AError( - root=InvalidRequestError( - message='Payload too large' - ) - ), + # If content lenght check is not diasbled, + # treat very large payloads as invalid request (-32600) before routing + if not self._disable_content_length_check: + with contextlib.suppress(Exception): + content_length = int( + request.headers.get('content-length', '0') ) + if content_length and content_length > MAX_CONTENT_LENGTH: + return self._generate_error_response( + request_id, + A2AError( + root=InvalidRequestError( + message='Payload too large' + ) + ), + ) logger.debug('Request body: %s', body) # 1) Validate base JSON-RPC structure only (-32600 on failure) try: diff --git a/src/a2a/server/apps/jsonrpc/starlette_app.py b/src/a2a/server/apps/jsonrpc/starlette_app.py index b268d043..da8cbff0 100644 --- a/src/a2a/server/apps/jsonrpc/starlette_app.py +++ b/src/a2a/server/apps/jsonrpc/starlette_app.py @@ -59,6 +59,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, + disable_content_length_check: bool = False, ) -> None: """Initializes the A2AStarletteApplication. @@ -76,6 +77,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. + disable_content_length_check: An optional, if True disables the check + for oversized payloads. """ if not _package_starlette_installed: raise ImportError( @@ -90,6 +93,7 @@ def __init__( # noqa: PLR0913 context_builder=context_builder, card_modifier=card_modifier, extended_card_modifier=extended_card_modifier, + disable_content_length_check=disable_content_length_check, ) def routes( diff --git a/tests/server/apps/jsonrpc/test_serialization.py b/tests/server/apps/jsonrpc/test_serialization.py index 9365017b..3519d987 100644 --- a/tests/server/apps/jsonrpc/test_serialization.py +++ b/tests/server/apps/jsonrpc/test_serialization.py @@ -136,6 +136,32 @@ def test_handle_oversized_payload(agent_card_with_api_key: AgentCard): assert data['error']['code'] == InvalidRequestError().code +def test_handle_oversized_payload_with_check_disabled( + agent_card_with_api_key: AgentCard, +): + """Test handling of oversized JSON payloads when the check is disabled.""" + handler = mock.AsyncMock() + app_instance = A2AStarletteApplication( + agent_card_with_api_key, handler, disable_content_length_check=True + ) + client = TestClient(app_instance.build()) + + large_string = 'a' * 11 * 1_000_000 # 11MB string + payload = { + 'jsonrpc': '2.0', + 'method': 'test', + 'id': 1, + 'params': {'data': large_string}, + } + + response = client.post('/', json=payload) + assert response.status_code == 200 + data = response.json() + # With the check disabled, it shouldn't return InvalidRequestError due to size. + # It will likely error out deeper in the handler, but not with the size-specific code. + assert data['error']['code'] != InvalidRequestError().code + + def test_handle_unicode_characters(agent_card_with_api_key: AgentCard): """Test handling of unicode characters in JSON payload.""" handler = mock.AsyncMock() From e43f469ef470a029554fc3bd652abb9bd4b0d3b9 Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 15:26:39 +0000 Subject: [PATCH 3/9] chore(tests): remove unused import of MAX_CONTENT_LENGTH in test_serialization.py --- tests/server/apps/jsonrpc/test_serialization.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/server/apps/jsonrpc/test_serialization.py b/tests/server/apps/jsonrpc/test_serialization.py index bd9190a4..3519d987 100644 --- a/tests/server/apps/jsonrpc/test_serialization.py +++ b/tests/server/apps/jsonrpc/test_serialization.py @@ -6,7 +6,6 @@ from pydantic import ValidationError from starlette.testclient import TestClient -from a2a.server.apps.jsonrpc.jsonrpc_app import MAX_CONTENT_LENGTH from a2a.server.apps import A2AFastAPIApplication, A2AStarletteApplication from a2a.types import ( APIKeySecurityScheme, From c53022f67b12e65c7c9418c496ea21d6e8f662b5 Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 15:37:56 +0000 Subject: [PATCH 4/9] feat: add option to disable oversized payload check in A2AFastAPIApplication --- src/a2a/server/apps/jsonrpc/fastapi_app.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/a2a/server/apps/jsonrpc/fastapi_app.py b/src/a2a/server/apps/jsonrpc/fastapi_app.py index 4ba7fdce..cdf76e06 100644 --- a/src/a2a/server/apps/jsonrpc/fastapi_app.py +++ b/src/a2a/server/apps/jsonrpc/fastapi_app.py @@ -77,6 +77,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, + disable_content_length_check: bool = False, ) -> None: """Initializes the A2AFastAPIApplication. @@ -94,6 +95,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. + disable_content_length_check: An optional, if True disables the check + for oversized payloads. """ if not _package_fastapi_installed: raise ImportError( @@ -108,6 +111,7 @@ def __init__( # noqa: PLR0913 context_builder=context_builder, card_modifier=card_modifier, extended_card_modifier=extended_card_modifier, + disable_content_length_check=disable_content_length_check, ) def add_routes_to_app( From 614ee0adbc5880cea066ec3477b3c31f0eb9b62d Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 15:50:53 +0000 Subject: [PATCH 5/9] Fix: typos --- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index e02ba252..c0ee90bb 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -295,7 +295,7 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 request_id, str | int ): request_id = None - # If content lenght check is not diasbled, + # If content lenght check is not disabled, # treat very large payloads as invalid request (-32600) before routing if not self._disable_content_length_check: with contextlib.suppress(Exception): From 2325318e43fd574e6bf576805dd74ce0e1853394 Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 15:56:53 +0000 Subject: [PATCH 6/9] Fix: typo and indentation inconsistency --- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 2 +- src/a2a/server/apps/jsonrpc/starlette_app.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index c0ee90bb..dc5169ff 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -295,7 +295,7 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 request_id, str | int ): request_id = None - # If content lenght check is not disabled, + # If content length check is not disabled, # treat very large payloads as invalid request (-32600) before routing if not self._disable_content_length_check: with contextlib.suppress(Exception): diff --git a/src/a2a/server/apps/jsonrpc/starlette_app.py b/src/a2a/server/apps/jsonrpc/starlette_app.py index da8cbff0..139398d6 100644 --- a/src/a2a/server/apps/jsonrpc/starlette_app.py +++ b/src/a2a/server/apps/jsonrpc/starlette_app.py @@ -78,7 +78,7 @@ def __init__( # noqa: PLR0913 the extended agent card before it is served. It receives the call context. disable_content_length_check: An optional, if True disables the check - for oversized payloads. + for oversized payloads. """ if not _package_starlette_installed: raise ImportError( From 22b111a797c70575ed4d67a669a019ef82243daa Mon Sep 17 00:00:00 2001 From: sokoliva Date: Fri, 14 Nov 2025 19:28:15 +0000 Subject: [PATCH 7/9] Fix Too many branches error by creating new method _check_content_length --- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 37 ++++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index dc5169ff..d0699f0a 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -265,6 +265,22 @@ def _generate_error_response( status_code=200, ) + def _check_content_length(self, request: Request) -> bool: + """Checks if the request content length exceeds the maximum allowed size. + + Args: + request: The incoming Starlette Request object. + + Returns: + True if the content length is within the allowed limit, False otherwise. + """ + if not self._disable_content_length_check: + with contextlib.suppress(Exception): + content_length = int(request.headers.get('content-length', '0')) + if content_length and content_length > MAX_CONTENT_LENGTH: + return False + return True + async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 """Handles incoming POST requests to the main A2A endpoint. @@ -297,20 +313,13 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 request_id = None # If content length check is not disabled, # treat very large payloads as invalid request (-32600) before routing - if not self._disable_content_length_check: - with contextlib.suppress(Exception): - content_length = int( - request.headers.get('content-length', '0') - ) - if content_length and content_length > MAX_CONTENT_LENGTH: - return self._generate_error_response( - request_id, - A2AError( - root=InvalidRequestError( - message='Payload too large' - ) - ), - ) + if not self._check_content_length(request): + return self._generate_error_response( + request_id, + A2AError( + root=InvalidRequestError(message='Payload too large') + ), + ) logger.debug('Request body: %s', body) # 1) Validate base JSON-RPC structure only (-32600 on failure) try: From b8f15ebcb55ea734526e9c9033ab55af031c9960 Mon Sep 17 00:00:00 2001 From: sokoliva Date: Mon, 17 Nov 2025 16:27:03 +0000 Subject: [PATCH 8/9] Define instance variable max_content_length. This commit depricates hardcoded MAX_CONTENT_LENGTH and introduces an instance variable max_content_length. --- src/a2a/server/apps/jsonrpc/fastapi_app.py | 8 ++--- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 29 +++++++++---------- src/a2a/server/apps/jsonrpc/starlette_app.py | 8 ++--- .../server/apps/jsonrpc/test_serialization.py | 20 +++++++++---- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/a2a/server/apps/jsonrpc/fastapi_app.py b/src/a2a/server/apps/jsonrpc/fastapi_app.py index cdf76e06..ace2c6ae 100644 --- a/src/a2a/server/apps/jsonrpc/fastapi_app.py +++ b/src/a2a/server/apps/jsonrpc/fastapi_app.py @@ -77,7 +77,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, - disable_content_length_check: bool = False, + max_content_length: int | None = 10 * 1024 * 1024, # 10MB ) -> None: """Initializes the A2AFastAPIApplication. @@ -95,8 +95,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. - disable_content_length_check: An optional, if True disables the check - for oversized payloads. + max_content_length: The maximum allowed content length for incoming + requests. Defaults to 10MB. Set to None for unbounded maximum. """ if not _package_fastapi_installed: raise ImportError( @@ -111,7 +111,7 @@ def __init__( # noqa: PLR0913 context_builder=context_builder, card_modifier=card_modifier, extended_card_modifier=extended_card_modifier, - disable_content_length_check=disable_content_length_check, + max_content_length=max_content_length, ) def add_routes_to_app( diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index d0699f0a..ff974828 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -91,8 +91,6 @@ Response = Any HTTP_413_REQUEST_ENTITY_TOO_LARGE = Any -MAX_CONTENT_LENGTH = 10_000_000 - class StarletteUserProxy(A2AUser): """Adapts the Starlette User class to the A2A user representation.""" @@ -134,7 +132,7 @@ def build(self, request: Request) -> ServerCallContext: """ user: A2AUser = UnauthenticatedUser() state = {} - with contextlib.suppress(Exception): + with contextlib.suppress(AttributeError): user = StarletteUserProxy(request.user) state['auth'] = request.auth state['headers'] = dict(request.headers) @@ -185,7 +183,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, - disable_content_length_check: bool = False, + max_content_length: int | None = 10 * 1024 * 1024, # 10MB ) -> None: """Initializes the JSONRPCApplication. @@ -203,8 +201,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. - disable_content_length_check: An optional, if True disables the check - for oversized payloads. + max_content_length: The maximum allowed content length for incoming + requests. Defaults to 10MB. Set to None for unbounded maximum. """ if not _package_starlette_installed: raise ImportError( @@ -223,7 +221,7 @@ def __init__( # noqa: PLR0913 extended_card_modifier=extended_card_modifier, ) self._context_builder = context_builder or DefaultCallContextBuilder() - self._disable_content_length_check = disable_content_length_check + self._max_content_length = max_content_length def _generate_error_response( self, request_id: str | int | None, error: JSONRPCError | A2AError @@ -265,19 +263,19 @@ def _generate_error_response( status_code=200, ) - def _check_content_length(self, request: Request) -> bool: - """Checks if the request content length exceeds the maximum allowed size. + def _allowed_content_length(self, request: Request) -> bool: + """Checks if the request content length is within the allowed maximum. Args: request: The incoming Starlette Request object. Returns: - True if the content length is within the allowed limit, False otherwise. + False if the content length is larger than the allowed maximum, True otherwise. """ - if not self._disable_content_length_check: - with contextlib.suppress(Exception): + if self._max_content_length is not None: + with contextlib.suppress(ValueError): content_length = int(request.headers.get('content-length', '0')) - if content_length and content_length > MAX_CONTENT_LENGTH: + if content_length and content_length > self._max_content_length: return False return True @@ -311,9 +309,8 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911 request_id, str | int ): request_id = None - # If content length check is not disabled, - # treat very large payloads as invalid request (-32600) before routing - if not self._check_content_length(request): + # Treat payloads lager than allowed as invalid request (-32600) before routing + if not self._allowed_content_length(request): return self._generate_error_response( request_id, A2AError( diff --git a/src/a2a/server/apps/jsonrpc/starlette_app.py b/src/a2a/server/apps/jsonrpc/starlette_app.py index 139398d6..1effa9d5 100644 --- a/src/a2a/server/apps/jsonrpc/starlette_app.py +++ b/src/a2a/server/apps/jsonrpc/starlette_app.py @@ -59,7 +59,7 @@ def __init__( # noqa: PLR0913 [AgentCard, ServerCallContext], AgentCard ] | None = None, - disable_content_length_check: bool = False, + max_content_length: int | None = 10 * 1024 * 1024, # 10MB ) -> None: """Initializes the A2AStarletteApplication. @@ -77,8 +77,8 @@ def __init__( # noqa: PLR0913 extended_card_modifier: An optional callback to dynamically modify the extended agent card before it is served. It receives the call context. - disable_content_length_check: An optional, if True disables the check - for oversized payloads. + max_content_length: The maximum allowed content length for incoming + requests. Defaults to 10MB. Set to None for unbounded maximum. """ if not _package_starlette_installed: raise ImportError( @@ -93,7 +93,7 @@ def __init__( # noqa: PLR0913 context_builder=context_builder, card_modifier=card_modifier, extended_card_modifier=extended_card_modifier, - disable_content_length_check=disable_content_length_check, + max_content_length=max_content_length, ) def routes( diff --git a/tests/server/apps/jsonrpc/test_serialization.py b/tests/server/apps/jsonrpc/test_serialization.py index 3519d987..f6778046 100644 --- a/tests/server/apps/jsonrpc/test_serialization.py +++ b/tests/server/apps/jsonrpc/test_serialization.py @@ -136,13 +136,22 @@ def test_handle_oversized_payload(agent_card_with_api_key: AgentCard): assert data['error']['code'] == InvalidRequestError().code -def test_handle_oversized_payload_with_check_disabled( +@pytest.mark.parametrize( + 'max_content_length', + [ + None, + 11 * 1024 * 1024, + 30 * 1024 * 1024, + ], +) +def test_handle_oversized_payload_with_max_content_length( agent_card_with_api_key: AgentCard, + max_content_length: int | None, ): - """Test handling of oversized JSON payloads when the check is disabled.""" + """Test handling of JSON payloads with sizes within custom max_content_length.""" handler = mock.AsyncMock() app_instance = A2AStarletteApplication( - agent_card_with_api_key, handler, disable_content_length_check=True + agent_card_with_api_key, handler, max_content_length=max_content_length ) client = TestClient(app_instance.build()) @@ -157,8 +166,9 @@ def test_handle_oversized_payload_with_check_disabled( response = client.post('/', json=payload) assert response.status_code == 200 data = response.json() - # With the check disabled, it shouldn't return InvalidRequestError due to size. - # It will likely error out deeper in the handler, but not with the size-specific code. + # When max_content_length is set, requests up to that size should not be + # rejected due to payload size. The request might fail for other reasons, + # but it shouldn't be an InvalidRequestError related to the content length. assert data['error']['code'] != InvalidRequestError().code From 89dda1e81634cae72e19b560dba7bc1da27f45c9 Mon Sep 17 00:00:00 2001 From: sokoliva Date: Mon, 17 Nov 2025 16:41:05 +0000 Subject: [PATCH 9/9] Revert change made in a previous commit. AttributeError -> Exception --- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index ff974828..3e7c2854 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -132,7 +132,7 @@ def build(self, request: Request) -> ServerCallContext: """ user: A2AUser = UnauthenticatedUser() state = {} - with contextlib.suppress(AttributeError): + with contextlib.suppress(Exception): user = StarletteUserProxy(request.user) state['auth'] = request.auth state['headers'] = dict(request.headers)