You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			102 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			102 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
from __future__ import annotations
 | 
						|
 | 
						|
import http.client as httplib
 | 
						|
from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect
 | 
						|
 | 
						|
from ..exceptions import HeaderParsingError
 | 
						|
 | 
						|
 | 
						|
def is_fp_closed(obj: object) -> bool:
 | 
						|
    """
 | 
						|
    Checks whether a given file-like object is closed.
 | 
						|
 | 
						|
    :param obj:
 | 
						|
        The file-like object to check.
 | 
						|
    """
 | 
						|
 | 
						|
    try:
 | 
						|
        # Check `isclosed()` first, in case Python3 doesn't set `closed`.
 | 
						|
        # GH Issue #928
 | 
						|
        return obj.isclosed()  # type: ignore[no-any-return, attr-defined]
 | 
						|
    except AttributeError:
 | 
						|
        pass
 | 
						|
 | 
						|
    try:
 | 
						|
        # Check via the official file-like-object way.
 | 
						|
        return obj.closed  # type: ignore[no-any-return, attr-defined]
 | 
						|
    except AttributeError:
 | 
						|
        pass
 | 
						|
 | 
						|
    try:
 | 
						|
        # Check if the object is a container for another file-like object that
 | 
						|
        # gets released on exhaustion (e.g. HTTPResponse).
 | 
						|
        return obj.fp is None  # type: ignore[attr-defined]
 | 
						|
    except AttributeError:
 | 
						|
        pass
 | 
						|
 | 
						|
    raise ValueError("Unable to determine whether fp is closed.")
 | 
						|
 | 
						|
 | 
						|
def assert_header_parsing(headers: httplib.HTTPMessage) -> None:
 | 
						|
    """
 | 
						|
    Asserts whether all headers have been successfully parsed.
 | 
						|
    Extracts encountered errors from the result of parsing headers.
 | 
						|
 | 
						|
    Only works on Python 3.
 | 
						|
 | 
						|
    :param http.client.HTTPMessage headers: Headers to verify.
 | 
						|
 | 
						|
    :raises urllib3.exceptions.HeaderParsingError:
 | 
						|
        If parsing errors are found.
 | 
						|
    """
 | 
						|
 | 
						|
    # This will fail silently if we pass in the wrong kind of parameter.
 | 
						|
    # To make debugging easier add an explicit check.
 | 
						|
    if not isinstance(headers, httplib.HTTPMessage):
 | 
						|
        raise TypeError(f"expected httplib.Message, got {type(headers)}.")
 | 
						|
 | 
						|
    unparsed_data = None
 | 
						|
 | 
						|
    # get_payload is actually email.message.Message.get_payload;
 | 
						|
    # we're only interested in the result if it's not a multipart message
 | 
						|
    if not headers.is_multipart():
 | 
						|
        payload = headers.get_payload()
 | 
						|
 | 
						|
        if isinstance(payload, (bytes, str)):
 | 
						|
            unparsed_data = payload
 | 
						|
 | 
						|
    # httplib is assuming a response body is available
 | 
						|
    # when parsing headers even when httplib only sends
 | 
						|
    # header data to parse_headers() This results in
 | 
						|
    # defects on multipart responses in particular.
 | 
						|
    # See: https://github.com/urllib3/urllib3/issues/800
 | 
						|
 | 
						|
    # So we ignore the following defects:
 | 
						|
    # - StartBoundaryNotFoundDefect:
 | 
						|
    #     The claimed start boundary was never found.
 | 
						|
    # - MultipartInvariantViolationDefect:
 | 
						|
    #     A message claimed to be a multipart but no subparts were found.
 | 
						|
    defects = [
 | 
						|
        defect
 | 
						|
        for defect in headers.defects
 | 
						|
        if not isinstance(
 | 
						|
            defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect)
 | 
						|
        )
 | 
						|
    ]
 | 
						|
 | 
						|
    if defects or unparsed_data:
 | 
						|
        raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data)
 | 
						|
 | 
						|
 | 
						|
def is_response_to_head(response: httplib.HTTPResponse) -> bool:
 | 
						|
    """
 | 
						|
    Checks whether the request of a response has been a HEAD-request.
 | 
						|
 | 
						|
    :param http.client.HTTPResponse response:
 | 
						|
        Response to check if the originating request
 | 
						|
        used 'HEAD' as a method.
 | 
						|
    """
 | 
						|
    # FIXME: Can we do this somehow without accessing private httplib _method?
 | 
						|
    method_str = response._method  # type: str  # type: ignore[attr-defined]
 | 
						|
    return method_str.upper() == "HEAD"
 |