@@ -317,16 +317,25 @@ def get(self, url: str, **kwargs: Unpack[RESTKwargs]) -> ResponseContextManager:
317317 return self .request ("GET" , url , ** kwargs )
318318
319319 def iter_lines (self , url : str , method : str = "GET" , ** kwargs ) -> Generator [str ]:
320- """Sends a iter_lines request"""
320+ """Sends a iter_lines request for streaming responses """
321321 response = self .request (method , url , stream = True , ** kwargs )
322322 response .raise_for_status ()
323+
323324 buffer = ""
324325 for chunk in response .iter_content (chunk_size = 1024 , decode_content = True ):
325- buffer += chunk .decode ("utf-8" )
326+ # Ensure that chunk is a string.
327+ if isinstance (chunk , bytes ):
328+ chunk = chunk .decode ('utf-8' , errors = 'replace' )
329+
330+ buffer += chunk
326331 while "\n " in buffer :
327332 line , buffer = buffer .split ("\n " , 1 )
328333 yield line
329334
335+ # Return to the last line that may be incomplete.
336+ if buffer :
337+ yield buffer
338+
330339 def head (self , url : str , ** kwargs : Unpack [RESTKwargs ]) -> ResponseContextManager :
331340 """Sends a HEAD request"""
332341 return self .request ("HEAD" , url , ** kwargs )
@@ -569,6 +578,38 @@ def raise_for_status(self):
569578 if error := getattr (self , "error" , None ):
570579 raise error
571580
581+ def iter_content (self , chunk_size = 1024 , decode_content = True ):
582+ """
583+ Simulates the `requests.Response.iter_content` method
584+
585+ Used for streaming response content
586+
587+ :param `chunk_size`: The size of the chunk read each time
588+
589+ :param `decode_content`: Whether to decode the content (from bytes to string)
590+
591+ :return: A generator that produces one chunk at a time
592+ """
593+ if not self ._response :
594+ raise LocustError ("Cannot iterate content on a response without _response attribute" )
595+
596+ while True :
597+ try :
598+ chunk = self ._response .read (chunk_size )
599+ if not chunk :
600+ break
601+
602+ if decode_content and isinstance (chunk , bytes ):
603+ try :
604+ chunk = chunk .decode ('utf-8' )
605+ except UnicodeDecodeError :
606+ # If decoding fails, preserve the data in byte format.
607+ pass
608+
609+ yield chunk
610+ except (HTTPConnectionClosed , ConnectionError ):
611+ break
612+
572613 @property
573614 def status_code (self ) -> int :
574615 """
0 commit comments