@@ -868,6 +868,33 @@ def _get_content_type_header(self, headers: dict) -> str | None:
868868 return value
869869 return None
870870
871+ def _get_request_body_safely (self , request : Any ) -> bytes | None :
872+ """Safely get request body content.
873+
874+ For multipart/streaming requests, the body may not be available
875+ until request.read() is called. This method handles the edge cases.
876+
877+ Args:
878+ request: httpx.Request object
879+
880+ Returns:
881+ bytes content or None if unavailable
882+ """
883+ try :
884+ # Check if content is already available (non-streaming requests)
885+ if hasattr (request , '_content' ) and request ._content is not None :
886+ return request .content
887+
888+ # For streaming/multipart requests, read the content
889+ # This is safe because:
890+ # - In REPLAY mode: we're not sending the actual request anyway
891+ # - In RECORD mode finalize: the request has already been sent
892+ request .read ()
893+ return request .content
894+ except Exception :
895+ # Content not available - could be streaming or error
896+ return None
897+
871898 def _try_get_mock_from_request_sync (
872899 self ,
873900 sdk : TuskDrift ,
@@ -898,11 +925,12 @@ def _try_get_mock_from_request_sync(
898925 if hasattr (request .url , 'params' ):
899926 params = dict (request .url .params )
900927
901- # Get body from request.content (already bytes)
928+ # Get body from request - handle streaming/multipart bodies
902929 body_base64 = None
903930 body_size = 0
904- if request .content :
905- body_base64 , body_size = self ._encode_body_to_base64 (request .content )
931+ request_body = self ._get_request_body_safely (request )
932+ if request_body :
933+ body_base64 , body_size = self ._encode_body_to_base64 (request_body )
906934
907935 raw_input_value = {
908936 "method" : method ,
@@ -1245,11 +1273,12 @@ def _finalize_span_from_request(
12451273 if hasattr (request .url , 'params' ):
12461274 params = dict (request .url .params )
12471275
1248- # Get request body from request.content (already bytes)
1276+ # Get request body - handle streaming/multipart bodies
12491277 body_base64 = None
12501278 body_size = 0
1251- if request .content :
1252- body_base64 , body_size = self ._encode_body_to_base64 (request .content )
1279+ request_body = self ._get_request_body_safely (request )
1280+ if request_body :
1281+ body_base64 , body_size = self ._encode_body_to_base64 (request_body )
12531282
12541283 input_value = {
12551284 "method" : method ,
@@ -1610,11 +1639,12 @@ async def _finalize_span_from_request_async(
16101639 if hasattr (request .url , 'params' ):
16111640 params = dict (request .url .params )
16121641
1613- # Get request body from request.content (already bytes)
1642+ # Get request body - handle streaming/multipart bodies
16141643 body_base64 = None
16151644 body_size = 0
1616- if request .content :
1617- body_base64 , body_size = self ._encode_body_to_base64 (request .content )
1645+ request_body = self ._get_request_body_safely (request )
1646+ if request_body :
1647+ body_base64 , body_size = self ._encode_body_to_base64 (request_body )
16181648
16191649 input_value = {
16201650 "method" : method ,
0 commit comments