@@ -91,6 +91,10 @@ class TraversalOptions:
9191class AgentError (RuntimeError ):
9292 """Base error for Service discovery operations."""
9393
94+ def __init__ (self , message : str , * , code : str | None = None ) -> None :
95+ super ().__init__ (message )
96+ self .code = code
97+
9498
9599class UnsupportedOperationError (AgentError ):
96100 def __init__ (self , operation : Operation ) -> None :
@@ -132,7 +136,12 @@ def __init__(
132136 self ._cache_partition = cache_partition
133137 self ._owns_transport = transport is None
134138 self ._transport = transport or HttpxTransport (allow_local_network = allow_local_network )
135- self ._supporting_transport = supporting_transport or self ._transport
139+ self ._owns_supporting_transport = supporting_transport is None
140+ self ._supporting_transport = (
141+ supporting_transport
142+ if supporting_transport is not None
143+ else HttpxTransport (allow_local_network = allow_local_network )
144+ )
136145
137146 async def __aenter__ (self ) -> ServiceClient :
138147 return self
@@ -141,8 +150,12 @@ async def __aexit__(self, *args: object) -> None:
141150 await self .aclose ()
142151
143152 async def aclose (self ) -> None :
144- if self ._owns_transport :
145- await self ._transport .aclose ()
153+ try :
154+ if self ._owns_transport :
155+ await self ._transport .aclose ()
156+ finally :
157+ if self ._owns_supporting_transport :
158+ await self ._supporting_transport .aclose ()
146159
147160 async def inspect (self ) -> Inspection :
148161 requested_url = f"{ self .service_origin } /.well-known/odp"
@@ -399,7 +412,9 @@ async def _request_cached(
399412 headers ["if-none-match" ] = cached .etag
400413 if cached .last_modified :
401414 headers ["if-modified-since" ] = cached .last_modified
402- response , final_url = await self ._request_raw (method , request_target , body , headers )
415+ response , final_url = await self ._request_raw (
416+ method , request_target , body , headers , maximum_bytes
417+ )
403418 if response .status == 304 :
404419 if cached is None :
405420 raise AgentError ("ODP response returned 304 without a cached representation" )
@@ -435,7 +450,7 @@ async def _request_cached(
435450 return _FetchedResponse (response .body , final_url , Freshness .FETCHED )
436451
437452 async def _request_raw (
438- self , method : str , target : str , body : bytes , conditional : dict [str , str ]
453+ self , method : str , target : str , body : bytes , conditional : dict [str , str ], maximum_bytes : int
439454 ) -> tuple [HttpResponse , str ]:
440455 redirect_origin = derive_service_origin (target )
441456 for redirects in range (_MAXIMUM_REDIRECTS + 1 ):
@@ -445,9 +460,11 @@ async def _request_raw(
445460 if body :
446461 headers ["content-type" ] = MEDIA_TYPE
447462 try :
448- response = await self ._transport .send (HttpRequest (method , target , headers , body ))
463+ response = await self ._transport .send (
464+ HttpRequest (method , target , headers , body , maximum_response_bytes = maximum_bytes )
465+ )
449466 except TransportError as error :
450- raise AgentError (f"ODP Service request failed: { error } " ) from error
467+ raise AgentError (f"ODP Service request failed: { error } " , code = error . code ) from error
451468 if response .status not in {301 , 302 , 303 , 307 , 308 }:
452469 return response , target
453470 if redirects == _MAXIMUM_REDIRECTS :
@@ -499,10 +516,17 @@ async def _supporting_json(
499516 visited .add (current )
500517 try :
501518 response = await self ._supporting_transport .send (
502- HttpRequest ("GET" , current , {"accept" : accept , ** conditional })
519+ HttpRequest (
520+ "GET" ,
521+ current ,
522+ {"accept" : accept , ** conditional },
523+ maximum_response_bytes = maximum_bytes ,
524+ )
503525 )
504526 except TransportError as error :
505- raise AgentError (f"ODP supporting document request failed: { error } " ) from error
527+ raise AgentError (
528+ f"ODP supporting document request failed: { error } " , code = error .code
529+ ) from error
506530 if response .status in {301 , 302 , 303 , 307 , 308 }:
507531 if redirects == _MAXIMUM_REDIRECTS :
508532 raise AgentError ("ODP supporting document exceeded five redirects" )
@@ -544,7 +568,9 @@ async def _supporting_json(
544568 response .headers ,
545569 )
546570 if len (response .body ) > maximum_bytes :
547- raise AgentError ("ODP supporting document exceeds its byte limit" )
571+ raise AgentError (
572+ "ODP supporting document exceeds its byte limit" , code = "RESPONSE_LIMIT_EXCEEDED"
573+ )
548574 content_type = response .headers .get ("content-type" , "" ).split (";" , 1 )[0 ].strip ().lower ()
549575 if content_type not in media_types :
550576 raise AgentError ("ODP supporting document has an unsupported media type" )
@@ -643,7 +669,7 @@ def _consume(response: HttpResponse, maximum_bytes: int, maximum_depth: int) ->
643669 if not 200 <= response .status < 300 :
644670 raise ServiceRequestError (response .status , _problem_message (response ), response .headers )
645671 if len (response .body ) > maximum_bytes :
646- raise AgentError ("ODP response exceeds its byte limit" )
672+ raise AgentError ("ODP response exceeds its byte limit" , code = "RESPONSE_LIMIT_EXCEEDED" )
647673 content_type = response .headers .get ("content-type" , "" ).split (";" , 1 )[0 ].strip ().lower ()
648674 if content_type != MEDIA_TYPE :
649675 raise AgentError (f"ODP response must use { MEDIA_TYPE } " )
0 commit comments