diff --git a/django/http/__init__.py b/django/http/__init__.py index 13cc8cea0d..69e9d51204 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -277,7 +277,20 @@ class HttpResponse(object): for key, value in self._headers.values()]) \ + '\n\n' + self.content + def _convert_to_ascii(self, *values): + "Convert all values to ascii strings" + for value in values: + if isinstance(value, unicode): + try: + yield value.encode('us-ascii') + except UnicodeError, e: + e.reason += ', HTTP response headers must be in US-ASCII format' + raise + else: + yield str(value) + def __setitem__(self, header, value): + header, value = self._convert_to_ascii(header, value) self._headers[header.lower()] = (header, value) def __delitem__(self, header): diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py index 5cfae029bb..8fa5cdc9f3 100644 --- a/tests/regressiontests/httpwrappers/tests.py +++ b/tests/regressiontests/httpwrappers/tests.py @@ -391,9 +391,43 @@ u'\ufffd' >>> q.getlist('foo') [u'bar', u'\ufffd'] + +###################################### +# HttpResponse with Unicode headers # +###################################### + +>>> r = HttpResponse() + +If we insert a unicode value it will be converted to an ascii +string. This makes sure we comply with the HTTP specifications. + +>>> r['value'] = u'test value' +>>> isinstance(r['value'], str) +True + +An error is raised When a unicode object with non-ascii is assigned. + +>>> r['value'] = u't\xebst value' # doctest:+ELLIPSIS +Traceback (most recent call last): +... +UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format + +The response also converts unicode keys to strings. + +>>> r[u'test'] = 'testing key' +>>> list(sorted(r.items()))[1] +('test', 'testing key') + +It will also raise errors for keys with non-ascii data. + +>>> r[u't\xebst'] = 'testing key' # doctest:+ELLIPSIS +Traceback (most recent call last): +... +UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format + """ -from django.http import QueryDict +from django.http import QueryDict, HttpResponse if __name__ == "__main__": import doctest