9191 Response = Any
9292 HTTP_413_REQUEST_ENTITY_TOO_LARGE = Any
9393
94- MAX_CONTENT_LENGTH = 10_000_000
95-
9694
9795class StarletteUserProxy (A2AUser ):
9896 """Adapts the Starlette User class to the A2A user representation."""
@@ -185,6 +183,7 @@ def __init__( # noqa: PLR0913
185183 [AgentCard , ServerCallContext ], AgentCard
186184 ]
187185 | None = None ,
186+ max_content_length : int | None = 10 * 1024 * 1024 , # 10MB
188187 ) -> None :
189188 """Initializes the JSONRPCApplication.
190189
@@ -202,6 +201,8 @@ def __init__( # noqa: PLR0913
202201 extended_card_modifier: An optional callback to dynamically modify
203202 the extended agent card before it is served. It receives the
204203 call context.
204+ max_content_length: The maximum allowed content length for incoming
205+ requests. Defaults to 10MB. Set to None for unbounded maximum.
205206 """
206207 if not _package_starlette_installed :
207208 raise ImportError (
@@ -220,6 +221,7 @@ def __init__( # noqa: PLR0913
220221 extended_card_modifier = extended_card_modifier ,
221222 )
222223 self ._context_builder = context_builder or DefaultCallContextBuilder ()
224+ self ._max_content_length = max_content_length
223225
224226 def _generate_error_response (
225227 self , request_id : str | int | None , error : JSONRPCError | A2AError
@@ -261,6 +263,22 @@ def _generate_error_response(
261263 status_code = 200 ,
262264 )
263265
266+ def _allowed_content_length (self , request : Request ) -> bool :
267+ """Checks if the request content length is within the allowed maximum.
268+
269+ Args:
270+ request: The incoming Starlette Request object.
271+
272+ Returns:
273+ False if the content length is larger than the allowed maximum, True otherwise.
274+ """
275+ if self ._max_content_length is not None :
276+ with contextlib .suppress (ValueError ):
277+ content_length = int (request .headers .get ('content-length' , '0' ))
278+ if content_length and content_length > self ._max_content_length :
279+ return False
280+ return True
281+
264282 async def _handle_requests (self , request : Request ) -> Response : # noqa: PLR0911
265283 """Handles incoming POST requests to the main A2A endpoint.
266284
@@ -291,18 +309,14 @@ async def _handle_requests(self, request: Request) -> Response: # noqa: PLR0911
291309 request_id , str | int
292310 ):
293311 request_id = None
294- # Treat very large payloads as invalid request (-32600) before routing
295- with contextlib .suppress (Exception ):
296- content_length = int (request .headers .get ('content-length' , '0' ))
297- if content_length and content_length > MAX_CONTENT_LENGTH :
298- return self ._generate_error_response (
299- request_id ,
300- A2AError (
301- root = InvalidRequestError (
302- message = 'Payload too large'
303- )
304- ),
305- )
312+ # Treat payloads lager than allowed as invalid request (-32600) before routing
313+ if not self ._allowed_content_length (request ):
314+ return self ._generate_error_response (
315+ request_id ,
316+ A2AError (
317+ root = InvalidRequestError (message = 'Payload too large' )
318+ ),
319+ )
306320 logger .debug ('Request body: %s' , body )
307321 # 1) Validate base JSON-RPC structure only (-32600 on failure)
308322 try :
0 commit comments