From 40b000cff157b6973b0480c15fbe11ff7fc3edea Mon Sep 17 00:00:00 2001 From: Sanchoyzer <412738+Sanchoyzer@users.noreply.github.com> Date: Sun, 20 Apr 2025 16:44:06 +0400 Subject: [PATCH] Add `content_type` for Response --- README.md | 2 +- docs/api.md | 1 + docs/index.md | 2 +- httpx/_main.py | 2 +- httpx/_models.py | 13 ++++++++++--- tests/test_content.py | 4 ++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 23992d9c24..7de56b92da 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Now, let's get started: >>> r.status_code 200 ->>> r.headers['content-type'] +>>> r.content_type 'text/html; charset=UTF-8' >>> r.text '\n\n\nExample Domain...' diff --git a/docs/api.md b/docs/api.md index f1bd50c993..8c9248e0cb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -61,6 +61,7 @@ * `.content` - **bytes** * `.text` - **str** * `.encoding` - **str** +* `.content_type` - **Optional[str]** * `.is_redirect` - **bool** * `.request` - **Request** * `.next_request` - **Optional[Request]** diff --git a/docs/index.md b/docs/index.md index c2210bc74f..798b189735 100644 --- a/docs/index.md +++ b/docs/index.md @@ -40,7 +40,7 @@ Now, let's get started: >>> r.status_code 200 ->>> r.headers['content-type'] +>>> r.content_type 'text/html; charset=UTF-8' >>> r.text '\n\n\nExample Domain...' diff --git a/httpx/_main.py b/httpx/_main.py index cffa4bb7db..c41680658e 100644 --- a/httpx/_main.py +++ b/httpx/_main.py @@ -101,7 +101,7 @@ def print_help() -> None: def get_lexer_for_response(response: Response) -> str: - content_type = response.headers.get("Content-Type") + content_type = response.content_type if content_type is not None: mime_type, _, _ = content_type.partition(";") try: diff --git a/httpx/_models.py b/httpx/_models.py index 2cc86321a4..1eec833fb4 100644 --- a/httpx/_models.py +++ b/httpx/_models.py @@ -690,11 +690,10 @@ def charset_encoding(self) -> str | None: """ Return the encoding, as specified by the Content-Type header. """ - content_type = self.headers.get("Content-Type") - if content_type is None: + if self.content_type is None: return None - return _parse_content_type_charset(content_type) + return _parse_content_type_charset(self.content_type) def _get_content_decoder(self) -> ContentDecoder: """ @@ -1075,6 +1074,14 @@ async def aclose(self) -> None: with request_context(request=self._request): await self.stream.aclose() + @property + def content_type(self) -> str | None: + """ + Return the Content-Type header. + """ + result = self.headers.get("Content-Type") + return str(result) if result else None + class Cookies(typing.MutableMapping[str, str]): """ diff --git a/tests/test_content.py b/tests/test_content.py index f63ec18a6b..862020470b 100644 --- a/tests/test_content.py +++ b/tests/test_content.py @@ -492,7 +492,7 @@ def test_ensure_ascii_false_with_french_characters(): assert ( "ça va" in response.text ), "ensure_ascii=False should preserve French accented characters" - assert response.headers["Content-Type"] == "application/json" + assert response.content_type == "application/json" def test_separators_for_compact_json(): @@ -501,7 +501,7 @@ def test_separators_for_compact_json(): assert ( response.text == '{"clé":"valeur","liste":[1,2,3]}' ), "separators=(',', ':') should produce a compact representation" - assert response.headers["Content-Type"] == "application/json" + assert response.content_type == "application/json" def test_allow_nan_false():