From c075508b4de8edf9db553b409f8a8ed2f26ecead Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Tue, 27 May 2025 17:00:29 +0100 Subject: Fixed #36411 -- Made HttpRequest.get_preferred_type() consider media type parameters. HttpRequest.get_preferred_type() did not account for parameters in Accept header media types (e.g., "text/vcard; version=3.0"). This caused incorrect content negotiation when multiple types differed only by parameters, reducing specificity as per RFC 7231 section 5.3.2 (https://datatracker.ietf.org/doc/html/rfc7231.html#section-5.3.2). This fix updates get_preferred_type() to treat media types with parameters as distinct, allowing more precise and standards-compliant matching. Thanks to magicfelix for the report, and to David Sanders and Sarah Boyce for the reviews. --- docs/ref/request-response.txt | 35 +++++++++++++++++++++++++++++++++++ docs/releases/5.2.2.txt | 5 +++++ 2 files changed, 40 insertions(+) (limited to 'docs') diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 9846a3a4b5..805b36023a 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -445,6 +445,41 @@ Methods >>> request.get_preferred_type(["application/xml", "text/plain"]) None + If the mime type includes parameters, these are also considered when + determining the preferred media type. For example, with an ``Accept`` + header of ``text/vcard;version=3.0,text/html;q=0.5``, the return value of + ``request.get_preferred_type()`` depends on the available media types: + + .. code-block:: pycon + + >>> request.get_preferred_type( + ... [ + ... "text/vcard; version=4.0", + ... "text/vcard; version=3.0", + ... "text/vcard", + ... "text/directory", + ... ] + ... ) + "text/vcard; version=3.0" + >>> request.get_preferred_type( + ... [ + ... "text/vcard; version=4.0", + ... "text/html", + ... ] + ... ) + "text/html" + >>> request.get_preferred_type( + ... [ + ... "text/vcard; version=4.0", + ... "text/vcard", + ... "text/directory", + ... ] + ... ) + None + + (For further details on how content negotiation is performed, see + :rfc:`7231#section-5.3.2`.) + Most browsers send ``Accept: */*`` by default, meaning they don't have a preference, in which case the first item in ``media_types`` would be returned. diff --git a/docs/releases/5.2.2.txt b/docs/releases/5.2.2.txt index 3870a3efa4..1a363ad55d 100644 --- a/docs/releases/5.2.2.txt +++ b/docs/releases/5.2.2.txt @@ -38,3 +38,8 @@ Bugfixes * Fixed a bug in Django 5.2 where calling ``QuerySet.in_bulk()`` with an ``id_list`` argument on models with a ``CompositePrimaryKey`` failed to observe database parameter limits (:ticket:`36416`). + +* Fixed a bug in Django 5.2 where :meth:`HttpRequest.get_preferred_type() + ` did not account for media type + parameters in ``Accept`` headers, reducing specificity in content negotiation + (:ticket:`36411`). -- cgit v1.3