diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index ea73ff59..d258916c 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -91,7 +91,7 @@ Response = Any HTTP_413_REQUEST_ENTITY_TOO_LARGE = Any -MAX_CONTENT_LENGTH = 1_000_000 +MAX_CONTENT_LENGTH = 10_000_000 class StarletteUserProxy(A2AUser): diff --git a/tests/server/apps/jsonrpc/test_serialization.py b/tests/server/apps/jsonrpc/test_serialization.py index df2e8a3a..9365017b 100644 --- a/tests/server/apps/jsonrpc/test_serialization.py +++ b/tests/server/apps/jsonrpc/test_serialization.py @@ -122,7 +122,7 @@ def test_handle_oversized_payload(agent_card_with_api_key: AgentCard): app_instance = A2AStarletteApplication(agent_card_with_api_key, handler) client = TestClient(app_instance.build()) - large_string = 'a' * 2_000_000 # 2MB string + large_string = 'a' * 11 * 1_000_000 # 11MB string payload = { 'jsonrpc': '2.0', 'method': 'test', @@ -130,22 +130,10 @@ def test_handle_oversized_payload(agent_card_with_api_key: AgentCard): 'params': {'data': large_string}, } - # Starlette/FastAPI's default max request size is around 1MB. - # This test will likely fail with a 413 Payload Too Large if the default is not increased. - # If the application is expected to handle larger payloads, the server configuration needs to be adjusted. - # For this test, we expect a 413 or a graceful JSON-RPC error if the app handles it. - - try: - response = client.post('/', json=payload) - # If the app handles it gracefully and returns a JSON-RPC error - if response.status_code == 200: - data = response.json() - assert data['error']['code'] == InvalidRequestError().code - else: - assert response.status_code == 413 - except Exception as e: - # Depending on server setup, it might just drop the connection for very large payloads - assert isinstance(e, ConnectionResetError | RuntimeError) + response = client.post('/', json=payload) + assert response.status_code == 200 + data = response.json() + assert data['error']['code'] == InvalidRequestError().code def test_handle_unicode_characters(agent_card_with_api_key: AgentCard): diff --git a/uv.lock b/uv.lock index 4dc93c18..5003ac40 100644 --- a/uv.lock +++ b/uv.lock @@ -18,6 +18,18 @@ dependencies = [ ] [package.optional-dependencies] +all = [ + { name = "cryptography" }, + { name = "fastapi" }, + { name = "grpcio" }, + { name = "grpcio-reflection" }, + { name = "grpcio-tools" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-sdk" }, + { name = "sqlalchemy", extra = ["aiomysql", "aiosqlite", "asyncio", "postgresql-asyncpg"] }, + { name = "sse-starlette" }, + { name = "starlette" }, +] encryption = [ { name = "cryptography" }, ] @@ -69,30 +81,45 @@ dev = [ { name = "types-protobuf" }, { name = "types-requests" }, { name = "uv-dynamic-versioning" }, + { name = "uvicorn" }, ] [package.metadata] requires-dist = [ + { name = "cryptography", marker = "extra == 'all'", specifier = ">=43.0.0" }, { name = "cryptography", marker = "extra == 'encryption'", specifier = ">=43.0.0" }, + { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.115.2" }, { name = "fastapi", marker = "extra == 'http-server'", specifier = ">=0.115.2" }, { name = "google-api-core", specifier = ">=1.26.0" }, + { name = "grpcio", marker = "extra == 'all'", specifier = ">=1.60" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.60" }, + { name = "grpcio-reflection", marker = "extra == 'all'", specifier = ">=1.7.0" }, { name = "grpcio-reflection", marker = "extra == 'grpc'", specifier = ">=1.7.0" }, + { name = "grpcio-tools", marker = "extra == 'all'", specifier = ">=1.60" }, { name = "grpcio-tools", marker = "extra == 'grpc'", specifier = ">=1.60" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "httpx-sse", specifier = ">=0.4.0" }, + { name = "opentelemetry-api", marker = "extra == 'all'", specifier = ">=1.33.0" }, { name = "opentelemetry-api", marker = "extra == 'telemetry'", specifier = ">=1.33.0" }, + { name = "opentelemetry-sdk", marker = "extra == 'all'", specifier = ">=1.33.0" }, { name = "opentelemetry-sdk", marker = "extra == 'telemetry'", specifier = ">=1.33.0" }, { name = "protobuf", specifier = ">=5.29.5" }, { name = "pydantic", specifier = ">=2.11.3" }, - { name = "sqlalchemy", extras = ["aiomysql", "aiosqlite", "asyncio", "postgresql-asyncpg"], marker = "extra == 'sql'", specifier = ">=2.0.0" }, + { name = "sqlalchemy", extras = ["aiomysql", "asyncio"], marker = "extra == 'all'", specifier = ">=2.0.0" }, { name = "sqlalchemy", extras = ["aiomysql", "asyncio"], marker = "extra == 'mysql'", specifier = ">=2.0.0" }, + { name = "sqlalchemy", extras = ["aiomysql", "asyncio"], marker = "extra == 'sql'", specifier = ">=2.0.0" }, + { name = "sqlalchemy", extras = ["aiosqlite", "asyncio"], marker = "extra == 'all'", specifier = ">=2.0.0" }, + { name = "sqlalchemy", extras = ["aiosqlite", "asyncio"], marker = "extra == 'sql'", specifier = ">=2.0.0" }, { name = "sqlalchemy", extras = ["aiosqlite", "asyncio"], marker = "extra == 'sqlite'", specifier = ">=2.0.0" }, + { name = "sqlalchemy", extras = ["asyncio", "postgresql-asyncpg"], marker = "extra == 'all'", specifier = ">=2.0.0" }, { name = "sqlalchemy", extras = ["asyncio", "postgresql-asyncpg"], marker = "extra == 'postgresql'", specifier = ">=2.0.0" }, + { name = "sqlalchemy", extras = ["asyncio", "postgresql-asyncpg"], marker = "extra == 'sql'", specifier = ">=2.0.0" }, + { name = "sse-starlette", marker = "extra == 'all'" }, { name = "sse-starlette", marker = "extra == 'http-server'" }, + { name = "starlette", marker = "extra == 'all'" }, { name = "starlette", marker = "extra == 'http-server'" }, ] -provides-extras = ["encryption", "grpc", "http-server", "mysql", "postgresql", "sql", "sqlite", "telemetry"] +provides-extras = ["all", "encryption", "grpc", "http-server", "mysql", "postgresql", "sql", "sqlite", "telemetry"] [package.metadata.requires-dev] dev = [ @@ -115,6 +142,7 @@ dev = [ { name = "types-protobuf" }, { name = "types-requests" }, { name = "uv-dynamic-versioning", specifier = ">=0.8.2" }, + { name = "uvicorn", specifier = ">=0.35.0" }, ] [[package]] @@ -1994,6 +2022,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bc/55/a6cffd78511faebf208d4ba1f119d489680668f8d36114564c6f499054b9/uv_dynamic_versioning-0.8.2-py3-none-any.whl", hash = "sha256:400ade6b4a3fc02895c3d24dd0214171e4d60106def343b39ad43143a2615e8c", size = 8851, upload-time = "2025-05-02T05:08:29.33Z" }, ] +[[package]] +name = "uvicorn" +version = "0.38.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/ce/f06b84e2697fef4688ca63bdb2fdf113ca0a3be33f94488f2cadb690b0cf/uvicorn-0.38.0.tar.gz", hash = "sha256:fd97093bdd120a2609fc0d3afe931d4d4ad688b6e75f0f929fde1bc36fe0e91d", size = 80605, upload-time = "2025-10-18T13:46:44.63Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/d9/d88e73ca598f4f6ff671fb5fde8a32925c2e08a637303a1d12883c7305fa/uvicorn-0.38.0-py3-none-any.whl", hash = "sha256:48c0afd214ceb59340075b4a052ea1ee91c16fbc2a9b1469cca0e54566977b02", size = 68109, upload-time = "2025-10-18T13:46:42.958Z" }, +] + [[package]] name = "virtualenv" version = "20.32.0"