def expected_http_body_size( request: request.Request, response: typing.Optional[response.Response] = None, expect_continue_as_0: bool = True): """ Args: - expect_continue_as_0: If true, incorrectly predict a body size of 0 for requests which are waiting for a 100 Continue response. Returns: The expected body length: - a positive integer, if the size is known in advance - None, if the size in unknown in advance (chunked encoding) - -1, if all data should be read until end of stream. Raises: exceptions.HttpSyntaxException, if the content length header is invalid """ # Determine response size according to # http://tools.ietf.org/html/rfc7230#section-3.3 if not response: headers = request.headers if expect_continue_as_0 and headers.get("expect", "").lower() == "100-continue": return 0 else: headers = response.headers if request.method.upper() == "HEAD": return 0 if 100 <= response.status_code <= 199: return 0 if response.status_code == 200 and request.method.upper() == "CONNECT": return 0 if response.status_code in (204, 304): return 0 if "chunked" in headers.get("transfer-encoding", "").lower(): return None if "content-length" in headers: try: sizes = headers.get_all("content-length") different_content_length_headers = any(x != sizes[0] for x in sizes) if different_content_length_headers: raise exceptions.HttpSyntaxException( "Conflicting Content Length Headers") size = int(sizes[0]) if size < 0: raise ValueError() return size except ValueError as e: raise exceptions.HttpSyntaxException( "Unparseable Content Length") from e if not response: return 0 return -1
def expected_http_body_size(request, response=None): """ Returns: The expected body length: - a positive integer, if the size is known in advance - None, if the size in unknown in advance (chunked encoding) - -1, if all data should be read until end of stream. Raises: exceptions.HttpSyntaxException, if the content length header is invalid """ # Determine response size according to # http://tools.ietf.org/html/rfc7230#section-3.3 if not response: headers = request.headers response_code = None is_request = True else: headers = response.headers response_code = response.status_code is_request = False if is_request: if headers.get("expect", "").lower() == "100-continue": return 0 else: if request.method.upper() == "HEAD": return 0 if 100 <= response_code <= 199: return 0 if response_code == 200 and request.method.upper() == "CONNECT": return 0 if response_code in (204, 304): return 0 if "chunked" in headers.get("transfer-encoding", "").lower(): return None if "content-length" in headers: try: sizes = headers.get_all("content-length") different_content_length_headers = any(x != sizes[0] for x in sizes) if different_content_length_headers: raise exceptions.HttpSyntaxException("Conflicting Content Length Headers") size = int(sizes[0]) if size < 0: raise ValueError() return size except ValueError: raise exceptions.HttpSyntaxException("Unparseable Content Length") if is_request: return 0 return -1