Skip to content

Commit b8eebef

Browse files
mikkelduifKludex
andauthored
Avoid duplicate charset on Content-Type (#2443)
* fix(response): avoid duplicated charset * Update docs/responses.md --------- Co-authored-by: Marcelo Trylesinski <[email protected]>
1 parent 8da52c2 commit b8eebef

File tree

3 files changed

+12
-2
lines changed

3 files changed

+12
-2
lines changed

docs/responses.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Signature: `Response(content, status_code=200, headers=None, media_type=None)`
1313

1414
Starlette will automatically include a Content-Length header. It will also
1515
include a Content-Type header, based on the media_type and appending a charset
16-
for text types.
16+
for text types, unless a charset has already been specified in the `media_type`.
1717

1818
Once you've instantiated a response, you can send it by calling it as an
1919
ASGI application instance.

starlette/responses.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ def init_headers(self, headers: typing.Mapping[str, str] | None = None) -> None:
7373

7474
content_type = self.media_type
7575
if content_type is not None and populate_content_type:
76-
if content_type.startswith("text/"):
76+
if (
77+
content_type.startswith("text/")
78+
and "charset=" not in content_type.lower()
79+
):
7780
content_type += "; charset=" + self.charset
7881
raw_headers.append((b"content-type", content_type.encode("latin-1")))
7982

tests/test_responses.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,13 @@ def test_non_empty_response(test_client_factory):
473473
assert response.headers["content-length"] == "2"
474474

475475

476+
def test_response_do_not_add_redundant_charset(test_client_factory):
477+
app = Response(media_type="text/plain; charset=utf-8")
478+
client = test_client_factory(app)
479+
response = client.get("/")
480+
assert response.headers["content-type"] == "text/plain; charset=utf-8"
481+
482+
476483
def test_file_response_known_size(tmpdir, test_client_factory):
477484
path = os.path.join(tmpdir, "xyz")
478485
content = b"<file content>" * 1000

0 commit comments

Comments
 (0)