Opened 4 years ago

Closed 4 years ago

#24598 closed Bug (duplicate)

JsonResponse loses encoding support in Content-Type header

Reported by: Curtis Maloney Owned by: nobody
Component: HTTP handling Version: 1.8
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Tim Graham)

By default when a content_type is not passed to HttpResponse it will create one from settings.DEFAULT_CONTENT_TYPE, and attach the encoding.

So, when unspecified, the header will appear as:

Content-Type: text/html; encoding=utf-8

However, if you specify the content_type, this action is not taken.

That's understandable in a "consenting adults" context, however the JsonResponse sets content_type using kwargs.setdefault, thus forcing the loss of encoding annotation in all responses.

I propose instead that HttpResponseBase check for a default_content_type property to override settings.DEFAULT_CONTENT_TYPE, thus:

  • django/http/response.py

    diff --git a/django/http/response.py b/django/http/response.py
    index c8d6930..40186b5 100644
    a b class HttpResponseBase(six.Iterator): 
    5454        self._reason_phrase = reason
    5555        self._charset = charset
    5656        if content_type is None:
    57             content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
    58                                               self.charset)
     57            content_type = getattr(self, 'default_content_type', settings.DEFAULT_CONTENT_TYPE)
     58            content_type = '%s; charset=%s' % (content_type, self.charset)
    5959        self['Content-Type'] = content_type

Change History (6)

comment:1 Changed 4 years ago by Curtis Maloney

Oops, forgot the second part of the patch:

@@ -470,11 +470,11 @@ class JsonResponse(HttpResponse):
     :param safe: Controls if only ``dict`` objects may be serialized. Defaults
       to ``True``.
     """
+    default_content_type = 'application/json'
 
     def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs):
         if safe and not isinstance(data, dict):
             raise TypeError('In order to allow non-dict objects to be '
                 'serialized set the safe parameter to False')
-        kwargs.setdefault('content_type', 'application/json')
         data = json.dumps(data, cls=encoder)
         super(JsonResponse, self).__init__(content=data, **kwargs)

comment:2 Changed 4 years ago by Tim Graham

Including a charset on application/json responses is invalid according to #23949.

comment:3 Changed 4 years ago by Tim Graham

Description: modified (diff)

comment:4 Changed 4 years ago by Claude Paroz

Isn't this one a simple duplicate of #23949?

comment:5 Changed 4 years ago by Tim Graham

I think so, but I thought I'd give Curtis an opportunity to say if there are any other valid use cases this patch might enable.

comment:6 Changed 4 years ago by Curtis Maloney

Resolution: duplicate
Status: newclosed

The reading is quite clear, so I guess the bug I was encountering which inspired this must be further down the line -- possibly in requests.

Note: See TracTickets for help on using tickets.
Back to Top