Set initial length value for Response content if available.
(self, request_method: str | None)
| 834 | return self._fp_bytes_read |
| 835 | |
| 836 | def _init_length(self, request_method: str | None) -> int | None: |
| 837 | """ |
| 838 | Set initial length value for Response content if available. |
| 839 | """ |
| 840 | length: int | None |
| 841 | content_length: str | None = self.headers.get("content-length") |
| 842 | |
| 843 | if content_length is not None: |
| 844 | if self.chunked: |
| 845 | # This Response will fail with an IncompleteRead if it can't be |
| 846 | # received as chunked. This method falls back to attempt reading |
| 847 | # the response before raising an exception. |
| 848 | log.warning( |
| 849 | "Received response with both Content-Length and " |
| 850 | "Transfer-Encoding set. This is expressly forbidden " |
| 851 | "by RFC 7230 sec 3.3.2. Ignoring Content-Length and " |
| 852 | "attempting to process response as Transfer-Encoding: " |
| 853 | "chunked." |
| 854 | ) |
| 855 | return None |
| 856 | |
| 857 | try: |
| 858 | # RFC 7230 section 3.3.2 specifies multiple content lengths can |
| 859 | # be sent in a single Content-Length header |
| 860 | # (e.g. Content-Length: 42, 42). This line ensures the values |
| 861 | # are all valid ints and that as long as the `set` length is 1, |
| 862 | # all values are the same. Otherwise, the header is invalid. |
| 863 | lengths = {int(val) for val in content_length.split(",")} |
| 864 | if len(lengths) > 1: |
| 865 | raise InvalidHeader( |
| 866 | "Content-Length contained multiple " |
| 867 | "unmatching values (%s)" % content_length |
| 868 | ) |
| 869 | length = lengths.pop() |
| 870 | except ValueError: |
| 871 | length = None |
| 872 | else: |
| 873 | if length < 0: |
| 874 | length = None |
| 875 | |
| 876 | else: # if content_length is None |
| 877 | length = None |
| 878 | |
| 879 | # Convert status to int for comparison |
| 880 | # In some cases, httplib returns a status of "_UNKNOWN" |
| 881 | try: |
| 882 | status = int(self.status) |
| 883 | except ValueError: |
| 884 | status = 0 |
| 885 | |
| 886 | # Check for responses that shouldn't include a body |
| 887 | if status in (204, 304) or 100 <= status < 200 or request_method == "HEAD": |
| 888 | length = 0 |
| 889 | |
| 890 | return length |
| 891 | |
| 892 | @contextmanager |
| 893 | def _error_catcher(self) -> typing.Generator[None]: |