Fixed #31789 -- Added a new headers interface to HttpResponse.

This commit is contained in:
Tom Carrick 2020-07-14 13:32:24 +02:00 committed by Mariusz Felisiak
parent 71ae1ab012
commit bcc2befd0e
47 changed files with 385 additions and 256 deletions

View File

@ -10,7 +10,7 @@ from django.utils.translation import gettext as _
class CSPMiddleware(MiddlewareMixin):
"""The admin's JavaScript should be compatible with CSP."""
def process_response(self, request, response):
response['Content-Security-Policy'] = "default-src 'self'"
response.headers['Content-Security-Policy'] = "default-src 'self'"
return response

View File

@ -24,5 +24,5 @@ class XViewMiddleware(MiddlewareMixin):
if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
(request.user.is_active and request.user.is_staff)):
response = HttpResponse()
response['X-View'] = get_view_name(view_func)
response.headers['X-View'] = get_view_name(view_func)
return response

View File

@ -14,7 +14,7 @@ def x_robots_tag(func):
@wraps(func)
def inner(request, *args, **kwargs):
response = func(request, *args, **kwargs)
response['X-Robots-Tag'] = 'noindex, noodp, noarchive'
response.headers['X-Robots-Tag'] = 'noindex, noodp, noarchive'
return response
return inner
@ -88,5 +88,5 @@ def sitemap(request, sitemaps, section=None,
if all_sites_lastmod and lastmod is not None:
# if lastmod is defined for all sites, set header so as
# ConditionalGetMiddleware is able to send 304 NOT MODIFIED
response['Last-Modified'] = http_date(timegm(lastmod))
response.headers['Last-Modified'] = http_date(timegm(lastmod))
return response

View File

@ -42,7 +42,7 @@ class Feed:
if hasattr(self, 'item_pubdate') or hasattr(self, 'item_updateddate'):
# if item_pubdate or item_updateddate is defined for the feed, set
# header so as ConditionalGetMiddleware is able to send 304 NOT MODIFIED
response['Last-Modified'] = http_date(
response.headers['Last-Modified'] = http_date(
timegm(feedgen.latest_post_date().utctimetuple()))
feedgen.write(response, 'utf-8')
return response

View File

@ -5,6 +5,7 @@ import os
import re
import sys
import time
from collections.abc import Mapping
from email.header import Header
from http.client import responses
from urllib.parse import quote, urlparse
@ -15,6 +16,7 @@ from django.core.exceptions import DisallowedRedirect
from django.core.serializers.json import DjangoJSONEncoder
from django.http.cookie import SimpleCookie
from django.utils import timezone
from django.utils.datastructures import CaseInsensitiveMapping
from django.utils.encoding import iri_to_uri
from django.utils.http import http_date
from django.utils.regex_helper import _lazy_re_compile
@ -22,6 +24,65 @@ from django.utils.regex_helper import _lazy_re_compile
_charset_from_content_type_re = _lazy_re_compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
class ResponseHeaders(CaseInsensitiveMapping):
def __init__(self, data):
"""
Populate the initial data using __setitem__ to ensure values are
correctly encoded.
"""
if not isinstance(data, Mapping):
data = {
k: v
for k, v in CaseInsensitiveMapping._destruct_iterable_mapping_values(data)
}
self._store = {}
for header, value in data.items():
self[header] = value
def _convert_to_charset(self, value, charset, mime_encode=False):
"""
Convert headers key/value to ascii/latin-1 native strings.
`charset` must be 'ascii' or 'latin-1'. If `mime_encode` is True and
`value` can't be represented in the given charset, apply MIME-encoding.
"""
if not isinstance(value, (bytes, str)):
value = str(value)
if (
(isinstance(value, bytes) and (b'\n' in value or b'\r' in value)) or
(isinstance(value, str) and ('\n' in value or '\r' in value))
):
raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
try:
if isinstance(value, str):
# Ensure string is valid in given charset
value.encode(charset)
else:
# Convert bytestring using given charset
value = value.decode(charset)
except UnicodeError as e:
if mime_encode:
value = Header(value, 'utf-8', maxlinelen=sys.maxsize).encode()
else:
e.reason += ', HTTP response headers must be in %s format' % charset
raise
return value
def __delitem__(self, key):
self.pop(key)
def __setitem__(self, key, value):
key = self._convert_to_charset(key, 'ascii')
value = self._convert_to_charset(value, 'latin-1', mime_encode=True)
self._store[key.lower()] = (key, value)
def pop(self, key, default=None):
return self._store.pop(key.lower(), default)
def setdefault(self, key, value):
if key not in self:
self[key] = value
class BadHeaderError(ValueError):
pass
@ -37,10 +98,7 @@ class HttpResponseBase:
status_code = 200
def __init__(self, content_type=None, status=None, reason=None, charset=None):
# _headers is a mapping of the lowercase name to the original case of
# the header (required for working with legacy systems) and the header
# value. Both the name of the header and its value are ASCII strings.
self._headers = {}
self.headers = ResponseHeaders({})
self._resource_closers = []
# This parameter is set by the handler. It's necessary to preserve the
# historical behavior of request_finished.
@ -95,7 +153,7 @@ class HttpResponseBase:
headers = [
(to_bytes(key, 'ascii') + b': ' + to_bytes(value, 'latin-1'))
for key, value in self._headers.values()
for key, value in self.headers.items()
]
return b'\r\n'.join(headers)
@ -103,57 +161,28 @@ class HttpResponseBase:
@property
def _content_type_for_repr(self):
return ', "%s"' % self['Content-Type'] if 'Content-Type' in self else ''
def _convert_to_charset(self, value, charset, mime_encode=False):
"""
Convert headers key/value to ascii/latin-1 native strings.
`charset` must be 'ascii' or 'latin-1'. If `mime_encode` is True and
`value` can't be represented in the given charset, apply MIME-encoding.
"""
if not isinstance(value, (bytes, str)):
value = str(value)
if ((isinstance(value, bytes) and (b'\n' in value or b'\r' in value)) or
isinstance(value, str) and ('\n' in value or '\r' in value)):
raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
try:
if isinstance(value, str):
# Ensure string is valid in given charset
value.encode(charset)
else:
# Convert bytestring using given charset
value = value.decode(charset)
except UnicodeError as e:
if mime_encode:
value = Header(value, 'utf-8', maxlinelen=sys.maxsize).encode()
else:
e.reason += ', HTTP response headers must be in %s format' % charset
raise
return value
return ', "%s"' % self.headers['Content-Type'] if 'Content-Type' in self.headers else ''
def __setitem__(self, header, value):
header = self._convert_to_charset(header, 'ascii')
value = self._convert_to_charset(value, 'latin-1', mime_encode=True)
self._headers[header.lower()] = (header, value)
self.headers[header] = value
def __delitem__(self, header):
self._headers.pop(header.lower(), False)
del self.headers[header]
def __getitem__(self, header):
return self._headers[header.lower()][1]
return self.headers[header]
def has_header(self, header):
"""Case-insensitive check for a header."""
return header.lower() in self._headers
return header in self.headers
__contains__ = has_header
def items(self):
return self._headers.values()
return self.headers.items()
def get(self, header, alternate=None):
return self._headers.get(header.lower(), (None, alternate))[1]
return self.headers.get(header, alternate)
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False, samesite=None):
@ -203,8 +232,7 @@ class HttpResponseBase:
def setdefault(self, key, value):
"""Set a header unless it has already been set."""
if key not in self:
self[key] = value
self.headers.setdefault(key, value)
def set_signed_cookie(self, key, value, salt='', **kwargs):
value = signing.get_cookie_signer(salt=key + salt).sign(value)
@ -430,19 +458,19 @@ class FileResponse(StreamingHttpResponse):
filename = getattr(filelike, 'name', None)
filename = filename if (isinstance(filename, str) and filename) else self.filename
if os.path.isabs(filename):
self['Content-Length'] = os.path.getsize(filelike.name)
self.headers['Content-Length'] = os.path.getsize(filelike.name)
elif hasattr(filelike, 'getbuffer'):
self['Content-Length'] = filelike.getbuffer().nbytes
self.headers['Content-Length'] = filelike.getbuffer().nbytes
if self.get('Content-Type', '').startswith('text/html'):
if self.headers.get('Content-Type', '').startswith('text/html'):
if filename:
content_type, encoding = mimetypes.guess_type(filename)
# Encoding isn't set to prevent browsers from automatically
# uncompressing files.
content_type = encoding_map.get(encoding, content_type)
self['Content-Type'] = content_type or 'application/octet-stream'
self.headers['Content-Type'] = content_type or 'application/octet-stream'
else:
self['Content-Type'] = 'application/octet-stream'
self.headers['Content-Type'] = 'application/octet-stream'
filename = self.filename or os.path.basename(filename)
if filename:
@ -452,9 +480,9 @@ class FileResponse(StreamingHttpResponse):
file_expr = 'filename="{}"'.format(filename)
except UnicodeEncodeError:
file_expr = "filename*=utf-8''{}".format(quote(filename))
self['Content-Disposition'] = '{}; {}'.format(disposition, file_expr)
self.headers['Content-Disposition'] = '{}; {}'.format(disposition, file_expr)
elif self.as_attachment:
self['Content-Disposition'] = 'attachment'
self.headers['Content-Disposition'] = 'attachment'
class HttpResponseRedirectBase(HttpResponse):

View File

@ -30,8 +30,10 @@ class XFrameOptionsMiddleware(MiddlewareMixin):
if getattr(response, 'xframe_options_exempt', False):
return response
response['X-Frame-Options'] = self.get_xframe_options_value(request,
response)
response.headers['X-Frame-Options'] = self.get_xframe_options_value(
request,
response,
)
return response
def get_xframe_options_value(self, request, response):

View File

@ -110,7 +110,7 @@ class CommonMiddleware(MiddlewareMixin):
# Add the Content-Length header to non-streaming responses if not
# already set.
if not response.streaming and not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))
response.headers['Content-Length'] = str(len(response.content))
return response

View File

@ -31,21 +31,21 @@ class GZipMiddleware(MiddlewareMixin):
# Delete the `Content-Length` header for streaming content, because
# we won't know the compressed size until we stream it.
response.streaming_content = compress_sequence(response.streaming_content)
del response['Content-Length']
del response.headers['Content-Length']
else:
# Return the compressed content only if it's actually shorter.
compressed_content = compress_string(response.content)
if len(compressed_content) >= len(response.content):
return response
response.content = compressed_content
response['Content-Length'] = str(len(response.content))
response.headers['Content-Length'] = str(len(response.content))
# If there is a strong ETag, make it weak to fulfill the requirements
# of RFC 7232 section-2.1 while also allowing conditional request
# matches on ETags.
etag = response.get('ETag')
if etag and etag.startswith('"'):
response['ETag'] = 'W/' + etag
response['Content-Encoding'] = 'gzip'
response.headers['ETag'] = 'W/' + etag
response.headers['Content-Encoding'] = 'gzip'
return response

View File

@ -57,5 +57,5 @@ class LocaleMiddleware(MiddlewareMixin):
if not (i18n_patterns_used and language_from_path):
patch_vary_headers(response, ('Accept-Language',))
response.setdefault('Content-Language', language)
response.headers.setdefault('Content-Language', language)
return response

View File

@ -38,18 +38,18 @@ class SecurityMiddleware(MiddlewareMixin):
sts_header = sts_header + "; includeSubDomains"
if self.sts_preload:
sts_header = sts_header + "; preload"
response['Strict-Transport-Security'] = sts_header
response.headers['Strict-Transport-Security'] = sts_header
if self.content_type_nosniff:
response.setdefault('X-Content-Type-Options', 'nosniff')
response.headers.setdefault('X-Content-Type-Options', 'nosniff')
if self.xss_filter:
response.setdefault('X-XSS-Protection', '1; mode=block')
response.headers.setdefault('X-XSS-Protection', '1; mode=block')
if self.referrer_policy:
# Support a comma-separated string or iterable of values to allow
# fallback.
response.setdefault('Referrer-Policy', ','.join(
response.headers.setdefault('Referrer-Policy', ','.join(
[v.strip() for v in self.referrer_policy.split(',')]
if isinstance(self.referrer_policy, str) else self.referrer_policy
))

View File

@ -62,7 +62,7 @@ def patch_cache_control(response, **kwargs):
cc = defaultdict(set)
if response.get('Cache-Control'):
for field in cc_delim_re.split(response['Cache-Control']):
for field in cc_delim_re.split(response.headers['Cache-Control']):
directive, value = dictitem(field)
if directive == 'no-cache':
# no-cache supports multiple field names.
@ -100,7 +100,7 @@ def patch_cache_control(response, **kwargs):
else:
directives.append(dictvalue(directive, values))
cc = ', '.join(directives)
response['Cache-Control'] = cc
response.headers['Cache-Control'] = cc
def get_max_age(response):
@ -110,7 +110,7 @@ def get_max_age(response):
"""
if not response.has_header('Cache-Control'):
return
cc = dict(_to_tuple(el) for el in cc_delim_re.split(response['Cache-Control']))
cc = dict(_to_tuple(el) for el in cc_delim_re.split(response.headers['Cache-Control']))
try:
return int(cc['max-age'])
except (ValueError, TypeError, KeyError):
@ -119,7 +119,7 @@ def get_max_age(response):
def set_response_etag(response):
if not response.streaming and response.content:
response['ETag'] = quote_etag(hashlib.md5(response.content).hexdigest())
response.headers['ETag'] = quote_etag(hashlib.md5(response.content).hexdigest())
return response
@ -140,7 +140,7 @@ def _not_modified(request, response=None):
# Last-Modified.
for header in ('Cache-Control', 'Content-Location', 'Date', 'ETag', 'Expires', 'Last-Modified', 'Vary'):
if header in response:
new_response[header] = response[header]
new_response.headers[header] = response.headers[header]
# Preserve cookies as per the cookie specification: "If a proxy server
# receives a response which contains a Set-cookie header, it should
@ -261,7 +261,7 @@ def patch_response_headers(response, cache_timeout=None):
if cache_timeout < 0:
cache_timeout = 0 # Can't have max-age negative
if not response.has_header('Expires'):
response['Expires'] = http_date(time.time() + cache_timeout)
response.headers['Expires'] = http_date(time.time() + cache_timeout)
patch_cache_control(response, max_age=cache_timeout)
@ -284,7 +284,7 @@ def patch_vary_headers(response, newheaders):
# implementations may rely on the order of the Vary contents in, say,
# computing an MD5 hash.
if response.has_header('Vary'):
vary_headers = cc_delim_re.split(response['Vary'])
vary_headers = cc_delim_re.split(response.headers['Vary'])
else:
vary_headers = []
# Use .lower() here so we treat headers as case-insensitive.
@ -293,9 +293,9 @@ def patch_vary_headers(response, newheaders):
if newheader.lower() not in existing_headers]
vary_headers += additional_headers
if '*' in vary_headers:
response['Vary'] = '*'
response.headers['Vary'] = '*'
else:
response['Vary'] = ', '.join(vary_headers)
response.headers['Vary'] = ', '.join(vary_headers)
def has_vary_header(response, header_query):
@ -304,7 +304,7 @@ def has_vary_header(response, header_query):
"""
if not response.has_header('Vary'):
return False
vary_headers = cc_delim_re.split(response['Vary'])
vary_headers = cc_delim_re.split(response.headers['Vary'])
existing_headers = {header.lower() for header in vary_headers}
return header_query.lower() in existing_headers
@ -391,7 +391,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cach
# in that case and would result in storing the same content under
# multiple keys in the cache. See #18191 for details.
headerlist = []
for header in cc_delim_re.split(response['Vary']):
for header in cc_delim_re.split(response.headers['Vary']):
header = header.upper().replace('-', '_')
if header != 'ACCEPT_LANGUAGE' or not is_accept_language_redundant:
headerlist.append('HTTP_' + header)

View File

@ -102,9 +102,9 @@ def condition(etag_func=None, last_modified_func=None):
# and if the request method is safe.
if request.method in ('GET', 'HEAD'):
if res_last_modified and not response.has_header('Last-Modified'):
response['Last-Modified'] = http_date(res_last_modified)
response.headers['Last-Modified'] = http_date(res_last_modified)
if res_etag:
response.setdefault('ETag', res_etag)
response.headers.setdefault('ETag', res_etag)
return response

View File

@ -107,8 +107,8 @@ class View:
def options(self, request, *args, **kwargs):
"""Handle responding to requests for the OPTIONS HTTP verb."""
response = HttpResponse()
response['Allow'] = ', '.join(self._allowed_methods())
response['Content-Length'] = '0'
response.headers['Allow'] = ', '.join(self._allowed_methods())
response.headers['Content-Length'] = '0'
return response
def _allowed_methods(self):

View File

@ -48,9 +48,9 @@ def serve(request, path, document_root=None, show_indexes=False):
content_type, encoding = mimetypes.guess_type(str(fullpath))
content_type = content_type or 'application/octet-stream'
response = FileResponse(fullpath.open('rb'), content_type=content_type)
response["Last-Modified"] = http_date(statobj.st_mtime)
response.headers["Last-Modified"] = http_date(statobj.st_mtime)
if encoding:
response["Content-Encoding"] = encoding
response.headers["Content-Encoding"] = encoding
return response

View File

@ -21,7 +21,7 @@ Here's an example::
def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
response.headers['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
writer = csv.writer(response)
writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
@ -88,7 +88,7 @@ the assembly and transmission of a large CSV file::
writer = csv.writer(pseudo_buffer)
response = StreamingHttpResponse((writer.writerow(row) for row in rows),
content_type="text/csv")
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
response.headers['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
return response
Using the template system
@ -109,7 +109,7 @@ Here's an example, which generates the same CSV file as above::
def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
response.headers['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
# The data is hard-coded here, but you could load it from a database or
# some other source.

View File

@ -700,17 +700,29 @@ generators are immediately closed.
If you need the response to be streamed from the iterator to the client, you
must use the :class:`StreamingHttpResponse` class instead.
.. _setting-header-fields:
Setting header fields
~~~~~~~~~~~~~~~~~~~~~
To set or remove a header field in your response, treat it like a dictionary::
To set or remove a header field in your response, use
:attr:`HttpResponse.headers`::
>>> response = HttpResponse()
>>> response.headers['Age'] = 120
>>> del response.headers['Age']
You can also manipulate headers by treating your response like a dictionary::
>>> response = HttpResponse()
>>> response['Age'] = 120
>>> del response['Age']
Note that unlike a dictionary, ``del`` doesn't raise ``KeyError`` if the header
field doesn't exist.
This proxies to ``HttpResponse.headers``, and is the original interface offered
by ``HttpResponse``.
When using this interface, unlike a dictionary, ``del`` doesn't raise
``KeyError`` if the header field doesn't exist.
For setting the ``Cache-Control`` and ``Vary`` header fields, it is recommended
to use the :func:`~django.utils.cache.patch_cache_control` and
@ -722,6 +734,10 @@ middleware, are not removed.
HTTP header fields cannot contain newlines. An attempt to set a header field
containing a newline character (CR or LF) will raise ``BadHeaderError``
.. versionchanged:: 3.2
The :attr:`HttpResponse.headers` interface was added.
Telling the browser to treat the response as a file attachment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -730,7 +746,7 @@ To tell the browser to treat the response as a file attachment, use the
this is how you might return a Microsoft Excel spreadsheet::
>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'
>>> response.headers['Content-Disposition'] = 'attachment; filename="foo.xls"'
There's nothing Django-specific about the ``Content-Disposition`` header, but
it's easy to forget the syntax, so we've included it here.
@ -742,6 +758,13 @@ Attributes
A bytestring representing the content, encoded from a string if necessary.
.. attribute:: HttpResponse.headers
.. versionadded:: 3.2
A case insensitive, dict-like object that provides an interface to all
HTTP headers on the response. See :ref:`setting-header-fields`.
.. attribute:: HttpResponse.charset
A string denoting the charset in which the response will be encoded. If not

View File

@ -309,7 +309,10 @@ Pagination
Requests and Responses
~~~~~~~~~~~~~~~~~~~~~~
* ...
* Response headers are now stored in :attr:`.HttpResponse.headers`. This can be
used instead of the original dict-like interface of ``HttpResponse`` objects.
Both interfaces will continue to be supported. See
:ref:`setting-header-fields` for details.
Security
~~~~~~~~

View File

@ -1159,10 +1159,10 @@ In this case, a caching mechanism (such as Django's own cache middleware) will
cache a separate version of the page for each unique user-agent.
The advantage to using the ``vary_on_headers`` decorator rather than manually
setting the ``Vary`` header (using something like
``response['Vary'] = 'user-agent'``) is that the decorator *adds* to the
``Vary`` header (which may already exist), rather than setting it from scratch
and potentially overriding anything that was already in there.
setting the ``Vary`` header (using something like ``response.headers['Vary'] =
'user-agent'``) is that the decorator *adds* to the ``Vary`` header (which may
already exist), rather than setting it from scratch and potentially overriding
anything that was already in there.
You can pass multiple headers to ``vary_on_headers()``::

View File

@ -119,7 +119,7 @@ And the view::
last_book = self.get_queryset().latest('publication_date')
response = HttpResponse()
# RFC 1123 date format
response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
response.headers['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
return response
If the view is accessed from a ``GET`` request, an object list is returned in

View File

@ -551,9 +551,9 @@ Specifically, a ``Response`` object has the following attributes:
If the given URL is not found, accessing this attribute will raise a
:exc:`~django.urls.Resolver404` exception.
You can also use dictionary syntax on the response object to query the value
of any settings in the HTTP headers. For example, you could determine the
content type of a response using ``response['Content-Type']``.
As with a normal response, you can also access the headers through
:attr:`.HttpResponse.headers`. For example, you could determine the content
type of a response using ``response.headers['Content-Type']``.
Exceptions
----------

View File

@ -13,7 +13,7 @@ class XViewMiddlewareTest(TestDataMixin, AdminDocsTestCase):
self.client.force_login(self.superuser)
response = self.client.head('/xview/func/')
self.assertIn('X-View', response)
self.assertEqual(response['X-View'], 'admin_docs.views.xview')
self.assertEqual(response.headers['X-View'], 'admin_docs.views.xview')
user.is_staff = False
user.save()
response = self.client.head('/xview/func/')
@ -31,7 +31,7 @@ class XViewMiddlewareTest(TestDataMixin, AdminDocsTestCase):
self.client.force_login(self.superuser)
response = self.client.head('/xview/class/')
self.assertIn('X-View', response)
self.assertEqual(response['X-View'], 'admin_docs.views.XViewClass')
self.assertEqual(response.headers['X-View'], 'admin_docs.views.XViewClass')
user.is_staff = False
user.save()
response = self.client.head('/xview/class/')
@ -45,7 +45,7 @@ class XViewMiddlewareTest(TestDataMixin, AdminDocsTestCase):
def test_callable_object_view(self):
self.client.force_login(self.superuser)
response = self.client.head('/xview/callable_object/')
self.assertEqual(response['X-View'], 'admin_docs.views.XViewCallableObject')
self.assertEqual(response.headers['X-View'], 'admin_docs.views.XViewCallableObject')
@override_settings(MIDDLEWARE=[])
def test_no_auth_middleware(self):

View File

@ -2964,7 +2964,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
)
self.assertEqual(response.status_code, 302) # temporary redirect
self.assertIn('/123_2Fhistory/', response['location']) # PK is quoted
self.assertIn('/123_2Fhistory/', response.headers['location']) # PK is quoted
@override_settings(ROOT_URLCONF='admin_views.urls')

View File

@ -993,7 +993,7 @@ class LogoutTest(AuthViewsTestCase):
in #25490.
"""
response = self.client.get('/logout/')
self.assertIn('no-store', response['Cache-Control'])
self.assertIn('no-store', response.headers['Cache-Control'])
def test_logout_with_overridden_redirect_url(self):
# Bug 11223

18
tests/cache/tests.py vendored
View File

@ -1700,9 +1700,9 @@ class CacheUtils(SimpleTestCase):
with self.subTest(initial_vary=initial_vary, newheaders=newheaders):
response = HttpResponse()
if initial_vary is not None:
response['Vary'] = initial_vary
response.headers['Vary'] = initial_vary
patch_vary_headers(response, newheaders)
self.assertEqual(response['Vary'], resulting_vary)
self.assertEqual(response.headers['Vary'], resulting_vary)
def test_get_cache_key(self):
request = self.factory.get(self.path)
@ -1753,7 +1753,7 @@ class CacheUtils(SimpleTestCase):
def test_learn_cache_key(self):
request = self.factory.head(self.path)
response = HttpResponse()
response['Vary'] = 'Pony'
response.headers['Vary'] = 'Pony'
# Make sure that the Vary header is added to the key hash
learn_cache_key(request, response)
@ -1795,9 +1795,9 @@ class CacheUtils(SimpleTestCase):
with self.subTest(initial_cc=initial_cc, newheaders=newheaders):
response = HttpResponse()
if initial_cc is not None:
response['Cache-Control'] = initial_cc
response.headers['Cache-Control'] = initial_cc
patch_cache_control(response, **newheaders)
parts = set(cc_delim_re.split(response['Cache-Control']))
parts = set(cc_delim_re.split(response.headers['Cache-Control']))
self.assertEqual(parts, expected_cc)
@ -1892,7 +1892,7 @@ class CacheI18nTest(SimpleTestCase):
request.META['HTTP_ACCEPT_LANGUAGE'] = accept_language
request.META['HTTP_ACCEPT_ENCODING'] = 'gzip;q=1.0, identity; q=0.5, *;q=0'
response = HttpResponse()
response['Vary'] = vary
response.headers['Vary'] = vary
key = learn_cache_key(request, response)
key2 = get_cache_key(request)
self.assertEqual(key, reference_key)
@ -1905,7 +1905,7 @@ class CacheI18nTest(SimpleTestCase):
request = self.factory.get(self.path)
request.META['HTTP_ACCEPT_ENCODING'] = 'gzip;q=1.0, identity; q=0.5, *;q=0'
response = HttpResponse()
response['Vary'] = 'accept-encoding'
response.headers['Vary'] = 'accept-encoding'
key = learn_cache_key(request, response)
self.assertIn(lang, key, "Cache keys should include the language name when translation is active")
self.check_accept_language_vary(
@ -2364,9 +2364,9 @@ class TestWithTemplateResponse(SimpleTestCase):
template = engines['django'].from_string("This is a test")
response = TemplateResponse(HttpRequest(), template)
if initial_vary is not None:
response['Vary'] = initial_vary
response.headers['Vary'] = initial_vary
patch_vary_headers(response, newheaders)
self.assertEqual(response['Vary'], resulting_vary)
self.assertEqual(response.headers['Vary'], resulting_vary)
def test_get_cache_key(self):
request = self.factory.get(self.path)

View File

@ -21,12 +21,12 @@ class ConditionalGet(SimpleTestCase):
self.assertEqual(response.content, FULL_RESPONSE.encode())
if response.request['REQUEST_METHOD'] in ('GET', 'HEAD'):
if check_last_modified:
self.assertEqual(response['Last-Modified'], LAST_MODIFIED_STR)
self.assertEqual(response.headers['Last-Modified'], LAST_MODIFIED_STR)
if check_etag:
self.assertEqual(response['ETag'], ETAG)
self.assertEqual(response.headers['ETag'], ETAG)
else:
self.assertNotIn('Last-Modified', response)
self.assertNotIn('ETag', response)
self.assertNotIn('Last-Modified', response.headers)
self.assertNotIn('ETag', response.headers)
def assertNotModified(self, response):
self.assertEqual(response.status_code, 304)

View File

@ -184,11 +184,11 @@ class ShortcutViewTests(TestCase):
response = shortcut(self.request, user_ct.id, obj.id)
self.assertEqual(
'http://%s/users/john/' % get_current_site(self.request).domain,
response._headers.get('location')[1]
response.headers.get('location')
)
with self.modify_settings(INSTALLED_APPS={'remove': 'django.contrib.sites'}):
response = shortcut(self.request, user_ct.id, obj.id)
self.assertEqual('http://Example.com/users/john/', response._headers.get('location')[1])
self.assertEqual('http://Example.com/users/john/', response.headers.get('location'))
def test_model_without_get_absolute_url(self):
"""The view returns 404 when Model.get_absolute_url() isn't defined."""

View File

@ -438,7 +438,7 @@ class XFrameOptionsDecoratorsTests(TestCase):
def a_view(request):
return HttpResponse()
r = a_view(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'DENY')
self.assertEqual(r.headers['X-Frame-Options'], 'DENY')
def test_sameorigin_decorator(self):
"""
@ -449,7 +449,7 @@ class XFrameOptionsDecoratorsTests(TestCase):
def a_view(request):
return HttpResponse()
r = a_view(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
def test_exempt_decorator(self):
"""
@ -477,6 +477,6 @@ class NeverCacheDecoratorTest(TestCase):
return HttpResponse()
r = a_view(HttpRequest())
self.assertEqual(
set(r['Cache-Control'].split(', ')),
set(r.headers['Cache-Control'].split(', ')),
{'max-age=0', 'no-cache', 'no-store', 'must-revalidate', 'private'},
)

View File

@ -195,7 +195,7 @@ class ViewTest(SimpleTestCase):
view = SimpleView.as_view()
response = view(request)
self.assertEqual(200, response.status_code)
self.assertTrue(response['Allow'])
self.assertTrue(response.headers['Allow'])
def test_options_for_get_view(self):
"""
@ -226,7 +226,7 @@ class ViewTest(SimpleTestCase):
def _assert_allows(self, response, *expected_methods):
"Assert allowed HTTP methods reported in the Allow response header"
response_allows = set(response['Allow'].split(', '))
response_allows = set(response.headers['Allow'].split(', '))
self.assertEqual(set(expected_methods + ('OPTIONS',)), response_allows)
def test_args_kwargs_request_on_self(self):
@ -390,7 +390,7 @@ class TemplateViewTest(SimpleTestCase):
def test_content_type(self):
response = self.client.get('/template/content_type/')
self.assertEqual(response['Content-Type'], 'text/plain')
self.assertEqual(response.headers['Content-Type'], 'text/plain')
def test_resolve_view(self):
match = resolve('/template/content_type/')
@ -461,12 +461,12 @@ class RedirectViewTest(SimpleTestCase):
"Named pattern parameter should reverse to the matching pattern"
response = RedirectView.as_view(pattern_name='artist_detail')(self.rf.get('/foo/'), pk=1)
self.assertEqual(response.status_code, 302)
self.assertEqual(response['Location'], '/detail/artist/1/')
self.assertEqual(response.headers['Location'], '/detail/artist/1/')
def test_named_url_pattern_using_args(self):
response = RedirectView.as_view(pattern_name='artist_detail')(self.rf.get('/foo/'), 1)
self.assertEqual(response.status_code, 302)
self.assertEqual(response['Location'], '/detail/artist/1/')
self.assertEqual(response.headers['Location'], '/detail/artist/1/')
def test_redirect_POST(self):
"Default is a temporary redirect"

View File

@ -292,44 +292,44 @@ class HttpResponseTests(unittest.TestCase):
r = HttpResponse()
# ASCII strings or bytes values are converted to strings.
r['key'] = 'test'
self.assertEqual(r['key'], 'test')
r['key'] = b'test'
self.assertEqual(r['key'], 'test')
r.headers['key'] = 'test'
self.assertEqual(r.headers['key'], 'test')
r.headers['key'] = b'test'
self.assertEqual(r.headers['key'], 'test')
self.assertIn(b'test', r.serialize_headers())
# Non-ASCII values are serialized to Latin-1.
r['key'] = 'café'
r.headers['key'] = 'café'
self.assertIn('café'.encode('latin-1'), r.serialize_headers())
# Other Unicode values are MIME-encoded (there's no way to pass them as
# bytes).
r['key'] = ''
self.assertEqual(r['key'], '=?utf-8?b?4oCg?=')
r.headers['key'] = ''
self.assertEqual(r.headers['key'], '=?utf-8?b?4oCg?=')
self.assertIn(b'=?utf-8?b?4oCg?=', r.serialize_headers())
# The response also converts string or bytes keys to strings, but requires
# them to contain ASCII
r = HttpResponse()
del r['Content-Type']
r['foo'] = 'bar'
headers = list(r.items())
del r.headers['Content-Type']
r.headers['foo'] = 'bar'
headers = list(r.headers.items())
self.assertEqual(len(headers), 1)
self.assertEqual(headers[0], ('foo', 'bar'))
r = HttpResponse()
del r['Content-Type']
r[b'foo'] = 'bar'
headers = list(r.items())
del r.headers['Content-Type']
r.headers[b'foo'] = 'bar'
headers = list(r.headers.items())
self.assertEqual(len(headers), 1)
self.assertEqual(headers[0], ('foo', 'bar'))
self.assertIsInstance(headers[0][0], str)
r = HttpResponse()
with self.assertRaises(UnicodeError):
r.__setitem__('føø', 'bar')
r.headers.__setitem__('føø', 'bar')
with self.assertRaises(UnicodeError):
r.__setitem__('føø'.encode(), 'bar')
r.headers.__setitem__('føø'.encode(), 'bar')
def test_long_line(self):
# Bug #20889: long lines trigger newlines to be added to headers
@ -337,18 +337,18 @@ class HttpResponseTests(unittest.TestCase):
h = HttpResponse()
f = b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz a\xcc\x88'
f = f.decode('utf-8')
h['Content-Disposition'] = 'attachment; filename="%s"' % f
h.headers['Content-Disposition'] = 'attachment; filename="%s"' % f
# This one is triggering https://bugs.python.org/issue20747, that is Python
# will itself insert a newline in the header
h['Content-Disposition'] = 'attachment; filename="EdelRot_Blu\u0308te (3)-0.JPG"'
h.headers['Content-Disposition'] = 'attachment; filename="EdelRot_Blu\u0308te (3)-0.JPG"'
def test_newlines_in_headers(self):
# Bug #10188: Do not allow newlines in headers (CR or LF)
r = HttpResponse()
with self.assertRaises(BadHeaderError):
r.__setitem__('test\rstr', 'test')
r.headers.__setitem__('test\rstr', 'test')
with self.assertRaises(BadHeaderError):
r.__setitem__('test\nstr', 'test')
r.headers.__setitem__('test\nstr', 'test')
def test_dict_behavior(self):
"""
@ -436,7 +436,7 @@ class HttpResponseTests(unittest.TestCase):
# with Content-Encoding header
r = HttpResponse()
r['Content-Encoding'] = 'winning'
r.headers['Content-Encoding'] = 'winning'
r.write(b'abc')
r.write(b'def')
self.assertEqual(r.content, b'abcdef')
@ -462,6 +462,14 @@ class HttpResponseTests(unittest.TestCase):
with self.assertRaises(DisallowedRedirect):
HttpResponsePermanentRedirect(url)
def test_header_deletion(self):
r = HttpResponse('hello')
r.headers['X-Foo'] = 'foo'
del r.headers['X-Foo']
self.assertNotIn('X-Foo', r.headers)
# del doesn't raise a KeyError on nonexistent headers.
del r.headers['X-Foo']
class HttpResponseSubclassesTests(SimpleTestCase):
def test_redirect(self):
@ -474,7 +482,7 @@ class HttpResponseSubclassesTests(SimpleTestCase):
content_type='text/html',
)
self.assertContains(response, 'The resource has temporarily moved', status_code=302)
self.assertEqual(response.url, response['Location'])
self.assertEqual(response.url, response.headers['Location'])
def test_redirect_lazy(self):
"""Make sure HttpResponseRedirect works with lazy strings."""
@ -523,7 +531,7 @@ class HttpResponseSubclassesTests(SimpleTestCase):
def test_not_allowed_repr_no_content_type(self):
response = HttpResponseNotAllowed(('GET', 'POST'))
del response['Content-Type']
del response.headers['Content-Type']
self.assertEqual(repr(response), '<HttpResponseNotAllowed [GET, POST] status_code=405>')
@ -785,3 +793,32 @@ class CookieTests(unittest.TestCase):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
C1 = pickle.loads(pickle.dumps(C, protocol=proto))
self.assertEqual(C1.output(), expected_output)
class HttpResponseHeadersTestCase(SimpleTestCase):
"""Headers by treating HttpResponse like a dictionary."""
def test_headers(self):
response = HttpResponse()
response['X-Foo'] = 'bar'
self.assertEqual(response['X-Foo'], 'bar')
self.assertEqual(response.headers['X-Foo'], 'bar')
self.assertIn('X-Foo', response)
self.assertIs(response.has_header('X-Foo'), True)
del response['X-Foo']
self.assertNotIn('X-Foo', response)
self.assertNotIn('X-Foo', response.headers)
# del doesn't raise a KeyError on nonexistent headers.
del response['X-Foo']
def test_headers_bytestring(self):
response = HttpResponse()
response['X-Foo'] = b'bar'
self.assertEqual(response['X-Foo'], 'bar')
self.assertEqual(response.headers['X-Foo'], 'bar')
def test_newlines_in_headers(self):
response = HttpResponse()
with self.assertRaises(BadHeaderError):
response['test\rstr'] = 'test'
with self.assertRaises(BadHeaderError):
response['test\nstr'] = 'test'

View File

@ -116,7 +116,7 @@ class PathUnusedTests(URLTestCaseBase):
def test_no_lang_activate(self):
response = self.client.get('/nl/foo/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response['content-language'], 'en')
self.assertEqual(response.headers['content-language'], 'en')
self.assertEqual(response.context['LANGUAGE_CODE'], 'en')
@ -200,7 +200,7 @@ class URLRedirectTests(URLTestCaseBase):
response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en')
self.assertRedirects(response, '/en/account/register/')
response = self.client.get(response['location'])
response = self.client.get(response.headers['location'])
self.assertEqual(response.status_code, 200)
def test_en_redirect_wrong_url(self):
@ -211,7 +211,7 @@ class URLRedirectTests(URLTestCaseBase):
response = self.client.get('/profiel/registreren/', HTTP_ACCEPT_LANGUAGE='nl')
self.assertRedirects(response, '/nl/profiel/registreren/')
response = self.client.get(response['location'])
response = self.client.get(response.headers['location'])
self.assertEqual(response.status_code, 200)
def test_nl_redirect_wrong_url(self):
@ -222,7 +222,7 @@ class URLRedirectTests(URLTestCaseBase):
response = self.client.get('/conta/registre-se/', HTTP_ACCEPT_LANGUAGE='pt-br')
self.assertRedirects(response, '/pt-br/conta/registre-se/')
response = self.client.get(response['location'])
response = self.client.get(response.headers['location'])
self.assertEqual(response.status_code, 200)
def test_pl_pl_redirect(self):
@ -230,7 +230,7 @@ class URLRedirectTests(URLTestCaseBase):
response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='pl-pl')
self.assertRedirects(response, '/en/account/register/')
response = self.client.get(response['location'])
response = self.client.get(response.headers['location'])
self.assertEqual(response.status_code, 200)
@override_settings(
@ -258,7 +258,7 @@ class URLVaryAcceptLanguageTests(URLTestCaseBase):
self.assertRedirects(response, '/en/account/register/')
self.assertFalse(response.get('Vary'))
response = self.client.get(response['location'])
response = self.client.get(response.headers['location'])
self.assertEqual(response.status_code, 200)
self.assertFalse(response.get('Vary'))
@ -297,7 +297,7 @@ class URLRedirectWithoutTrailingSlashSettingTests(URLTestCaseBase):
response = self.client.get('/account/register-without-slash', HTTP_ACCEPT_LANGUAGE='en')
self.assertRedirects(response, '/en/account/register-without-slash', 302)
response = self.client.get(response['location'])
response = self.client.get(response.headers['location'])
self.assertEqual(response.status_code, 200)
@ -310,13 +310,13 @@ class URLResponseTests(URLTestCaseBase):
def test_en_url(self):
response = self.client.get('/en/account/register/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response['content-language'], 'en')
self.assertEqual(response.headers['content-language'], 'en')
self.assertEqual(response.context['LANGUAGE_CODE'], 'en')
def test_nl_url(self):
response = self.client.get('/nl/profiel/registreren/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response['content-language'], 'nl')
self.assertEqual(response.headers['content-language'], 'nl')
self.assertEqual(response.context['LANGUAGE_CODE'], 'nl')
def test_wrong_en_prefix(self):
@ -330,19 +330,19 @@ class URLResponseTests(URLTestCaseBase):
def test_pt_br_url(self):
response = self.client.get('/pt-br/conta/registre-se/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response['content-language'], 'pt-br')
self.assertEqual(response.headers['content-language'], 'pt-br')
self.assertEqual(response.context['LANGUAGE_CODE'], 'pt-br')
def test_en_path(self):
response = self.client.get('/en/account/register-as-path/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response['content-language'], 'en')
self.assertEqual(response.headers['content-language'], 'en')
self.assertEqual(response.context['LANGUAGE_CODE'], 'en')
def test_nl_path(self):
response = self.client.get('/nl/profiel/registreren-als-pad/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response['content-language'], 'nl')
self.assertEqual(response.headers['content-language'], 'nl')
self.assertEqual(response.context['LANGUAGE_CODE'], 'nl')

View File

@ -17,7 +17,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
response = HttpResponse(*args, **kwargs)
if headers:
for k, v in headers.items():
response[k] = v
response.headers[k] = v
return response
return get_response
@ -47,7 +47,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
"Strict-Transport-Security: max-age=3600" to the response.
"""
self.assertEqual(
self.process_response(secure=True)["Strict-Transport-Security"],
self.process_response(secure=True).headers['Strict-Transport-Security'],
'max-age=3600',
)
@ -60,7 +60,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
response = self.process_response(
secure=True,
headers={"Strict-Transport-Security": "max-age=7200"})
self.assertEqual(response["Strict-Transport-Security"], "max-age=7200")
self.assertEqual(response.headers["Strict-Transport-Security"], "max-age=7200")
@override_settings(SECURE_HSTS_SECONDS=3600)
def test_sts_only_if_secure(self):
@ -68,7 +68,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
The "Strict-Transport-Security" header is not added to responses going
over an insecure connection.
"""
self.assertNotIn("Strict-Transport-Security", self.process_response(secure=False))
self.assertNotIn(
'Strict-Transport-Security',
self.process_response(secure=False).headers,
)
@override_settings(SECURE_HSTS_SECONDS=0)
def test_sts_off(self):
@ -76,7 +79,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
With SECURE_HSTS_SECONDS=0, the middleware does not add a
"Strict-Transport-Security" header to the response.
"""
self.assertNotIn("Strict-Transport-Security", self.process_response(secure=True))
self.assertNotIn(
'Strict-Transport-Security',
self.process_response(secure=True).headers,
)
@override_settings(SECURE_HSTS_SECONDS=600, SECURE_HSTS_INCLUDE_SUBDOMAINS=True)
def test_sts_include_subdomains(self):
@ -86,7 +92,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
"includeSubDomains" directive to the response.
"""
response = self.process_response(secure=True)
self.assertEqual(response["Strict-Transport-Security"], "max-age=600; includeSubDomains")
self.assertEqual(
response.headers['Strict-Transport-Security'],
'max-age=600; includeSubDomains',
)
@override_settings(SECURE_HSTS_SECONDS=600, SECURE_HSTS_INCLUDE_SUBDOMAINS=False)
def test_sts_no_include_subdomains(self):
@ -96,7 +105,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
the "includeSubDomains" directive to the response.
"""
response = self.process_response(secure=True)
self.assertEqual(response["Strict-Transport-Security"], "max-age=600")
self.assertEqual(response.headers["Strict-Transport-Security"], "max-age=600")
@override_settings(SECURE_HSTS_SECONDS=10886400, SECURE_HSTS_PRELOAD=True)
def test_sts_preload(self):
@ -106,7 +115,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
directive to the response.
"""
response = self.process_response(secure=True)
self.assertEqual(response["Strict-Transport-Security"], "max-age=10886400; preload")
self.assertEqual(
response.headers['Strict-Transport-Security'],
'max-age=10886400; preload',
)
@override_settings(SECURE_HSTS_SECONDS=10886400, SECURE_HSTS_INCLUDE_SUBDOMAINS=True, SECURE_HSTS_PRELOAD=True)
def test_sts_subdomains_and_preload(self):
@ -117,7 +129,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
to the response.
"""
response = self.process_response(secure=True)
self.assertEqual(response["Strict-Transport-Security"], "max-age=10886400; includeSubDomains; preload")
self.assertEqual(
response.headers['Strict-Transport-Security'],
'max-age=10886400; includeSubDomains; preload',
)
@override_settings(SECURE_HSTS_SECONDS=10886400, SECURE_HSTS_PRELOAD=False)
def test_sts_no_preload(self):
@ -127,7 +142,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
the "preload" directive to the response.
"""
response = self.process_response(secure=True)
self.assertEqual(response["Strict-Transport-Security"], "max-age=10886400")
self.assertEqual(
response.headers['Strict-Transport-Security'],
'max-age=10886400',
)
@override_settings(SECURE_CONTENT_TYPE_NOSNIFF=True)
def test_content_type_on(self):
@ -135,7 +153,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
With SECURE_CONTENT_TYPE_NOSNIFF set to True, the middleware adds
"X-Content-Type-Options: nosniff" header to the response.
"""
self.assertEqual(self.process_response()["X-Content-Type-Options"], "nosniff")
self.assertEqual(
self.process_response().headers['X-Content-Type-Options'],
'nosniff',
)
@override_settings(SECURE_CONTENT_TYPE_NOSNIFF=True)
def test_content_type_already_present(self):
@ -144,7 +165,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
already present in the response.
"""
response = self.process_response(secure=True, headers={"X-Content-Type-Options": "foo"})
self.assertEqual(response["X-Content-Type-Options"], "foo")
self.assertEqual(response.headers["X-Content-Type-Options"], "foo")
@override_settings(SECURE_CONTENT_TYPE_NOSNIFF=False)
def test_content_type_off(self):
@ -152,7 +173,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
With SECURE_CONTENT_TYPE_NOSNIFF False, the middleware does not add an
"X-Content-Type-Options" header to the response.
"""
self.assertNotIn("X-Content-Type-Options", self.process_response())
self.assertNotIn('X-Content-Type-Options', self.process_response().headers)
@override_settings(SECURE_BROWSER_XSS_FILTER=True)
def test_xss_filter_on(self):
@ -160,7 +181,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
With SECURE_BROWSER_XSS_FILTER set to True, the middleware adds
"s-xss-protection: 1; mode=block" header to the response.
"""
self.assertEqual(self.process_response()["X-XSS-Protection"], "1; mode=block")
self.assertEqual(
self.process_response().headers['X-XSS-Protection'],
'1; mode=block',
)
@override_settings(SECURE_BROWSER_XSS_FILTER=True)
def test_xss_filter_already_present(self):
@ -169,7 +193,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
already present in the response.
"""
response = self.process_response(secure=True, headers={"X-XSS-Protection": "foo"})
self.assertEqual(response["X-XSS-Protection"], "foo")
self.assertEqual(response.headers["X-XSS-Protection"], "foo")
@override_settings(SECURE_BROWSER_XSS_FILTER=False)
def test_xss_filter_off(self):
@ -177,7 +201,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
With SECURE_BROWSER_XSS_FILTER set to False, the middleware does not
add an "X-XSS-Protection" header to the response.
"""
self.assertNotIn("X-XSS-Protection", self.process_response())
self.assertNotIn('X-XSS-Protection', self.process_response().headers)
@override_settings(SECURE_SSL_REDIRECT=True)
def test_ssl_redirect_on(self):
@ -229,7 +253,7 @@ class SecurityMiddlewareTest(SimpleTestCase):
With SECURE_REFERRER_POLICY set to None, the middleware does not add a
"Referrer-Policy" header to the response.
"""
self.assertNotIn('Referrer-Policy', self.process_response())
self.assertNotIn('Referrer-Policy', self.process_response().headers)
def test_referrer_policy_on(self):
"""
@ -245,7 +269,10 @@ class SecurityMiddlewareTest(SimpleTestCase):
)
for value, expected in tests:
with self.subTest(value=value), override_settings(SECURE_REFERRER_POLICY=value):
self.assertEqual(self.process_response()['Referrer-Policy'], expected)
self.assertEqual(
self.process_response().headers['Referrer-Policy'],
expected,
)
@override_settings(SECURE_REFERRER_POLICY='strict-origin')
def test_referrer_policy_already_present(self):
@ -254,4 +281,4 @@ class SecurityMiddlewareTest(SimpleTestCase):
present in the response.
"""
response = self.process_response(headers={'Referrer-Policy': 'unsafe-url'})
self.assertEqual(response['Referrer-Policy'], 'unsafe-url')
self.assertEqual(response.headers['Referrer-Policy'], 'unsafe-url')

View File

@ -292,7 +292,7 @@ class CommonMiddlewareTest(SimpleTestCase):
return response
response = CommonMiddleware(get_response)(self.rf.get('/'))
self.assertEqual(int(response['Content-Length']), len(response.content))
self.assertEqual(int(response.headers['Content-Length']), len(response.content))
def test_content_length_header_not_added_for_streaming_response(self):
def get_response(req):
@ -308,11 +308,11 @@ class CommonMiddlewareTest(SimpleTestCase):
def get_response(req):
response = HttpResponse()
response['Content-Length'] = bad_content_length
response.headers['Content-Length'] = bad_content_length
return response
response = CommonMiddleware(get_response)(self.rf.get('/'))
self.assertEqual(int(response['Content-Length']), bad_content_length)
self.assertEqual(int(response.headers['Content-Length']), bad_content_length)
# Other tests
@ -607,7 +607,7 @@ class ConditionalGetMiddlewareTest(SimpleTestCase):
self.assertEqual(new_response.status_code, 304)
base_response = get_response(self.req)
for header in ('Cache-Control', 'Content-Location', 'Date', 'ETag', 'Expires', 'Last-Modified', 'Vary'):
self.assertEqual(new_response[header], base_response[header])
self.assertEqual(new_response.headers[header], base_response.headers[header])
self.assertEqual(new_response.cookies, base_response.cookies)
self.assertNotIn('Content-Language', new_response)
@ -622,7 +622,7 @@ class ConditionalGetMiddlewareTest(SimpleTestCase):
return HttpResponse(status=200)
response = ConditionalGetMiddleware(self.get_response)(self.req)
etag = response['ETag']
etag = response.headers['ETag']
put_request = self.request_factory.put('/', HTTP_IF_MATCH=etag)
conditional_get_response = ConditionalGetMiddleware(get_200_response)(put_request)
self.assertEqual(conditional_get_response.status_code, 200) # should never be a 412
@ -653,11 +653,11 @@ class XFrameOptionsMiddlewareTest(SimpleTestCase):
"""
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
r = XFrameOptionsMiddleware(get_response_empty)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
with override_settings(X_FRAME_OPTIONS='sameorigin'):
r = XFrameOptionsMiddleware(get_response_empty)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
def test_deny(self):
"""
@ -666,11 +666,11 @@ class XFrameOptionsMiddlewareTest(SimpleTestCase):
"""
with override_settings(X_FRAME_OPTIONS='DENY'):
r = XFrameOptionsMiddleware(get_response_empty)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'DENY')
self.assertEqual(r.headers['X-Frame-Options'], 'DENY')
with override_settings(X_FRAME_OPTIONS='deny'):
r = XFrameOptionsMiddleware(get_response_empty)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'DENY')
self.assertEqual(r.headers['X-Frame-Options'], 'DENY')
def test_defaults_sameorigin(self):
"""
@ -680,7 +680,7 @@ class XFrameOptionsMiddlewareTest(SimpleTestCase):
with override_settings(X_FRAME_OPTIONS=None):
del settings.X_FRAME_OPTIONS # restored by override_settings
r = XFrameOptionsMiddleware(get_response_empty)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'DENY')
self.assertEqual(r.headers['X-Frame-Options'], 'DENY')
def test_dont_set_if_set(self):
"""
@ -689,21 +689,21 @@ class XFrameOptionsMiddlewareTest(SimpleTestCase):
"""
def same_origin_response(request):
response = HttpResponse()
response['X-Frame-Options'] = 'SAMEORIGIN'
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
return response
def deny_response(request):
response = HttpResponse()
response['X-Frame-Options'] = 'DENY'
response.headers['X-Frame-Options'] = 'DENY'
return response
with override_settings(X_FRAME_OPTIONS='DENY'):
r = XFrameOptionsMiddleware(same_origin_response)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
r = XFrameOptionsMiddleware(deny_response)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'DENY')
self.assertEqual(r.headers['X-Frame-Options'], 'DENY')
def test_response_exempt(self):
"""
@ -722,10 +722,10 @@ class XFrameOptionsMiddlewareTest(SimpleTestCase):
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
r = XFrameOptionsMiddleware(xframe_not_exempt_response)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
r = XFrameOptionsMiddleware(xframe_exempt_response)(HttpRequest())
self.assertIsNone(r.get('X-Frame-Options'))
self.assertIsNone(r.headers.get('X-Frame-Options'))
def test_is_extendable(self):
"""
@ -749,16 +749,16 @@ class XFrameOptionsMiddlewareTest(SimpleTestCase):
with override_settings(X_FRAME_OPTIONS='DENY'):
r = OtherXFrameOptionsMiddleware(same_origin_response)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
request = HttpRequest()
request.sameorigin = True
r = OtherXFrameOptionsMiddleware(get_response_empty)(request)
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
self.assertEqual(r.headers['X-Frame-Options'], 'SAMEORIGIN')
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
r = OtherXFrameOptionsMiddleware(get_response_empty)(HttpRequest())
self.assertEqual(r['X-Frame-Options'], 'DENY')
self.assertEqual(r.headers['X-Frame-Options'], 'DENY')
class GZipMiddlewareTest(SimpleTestCase):
@ -916,12 +916,12 @@ class ETagGZipMiddlewareTest(SimpleTestCase):
"""
def get_response(req):
response = HttpResponse(self.compressible_string)
response['ETag'] = '"eggs"'
response.headers['ETag'] = '"eggs"'
return response
request = self.rf.get('/', HTTP_ACCEPT_ENCODING='gzip, deflate')
gzip_response = GZipMiddleware(get_response)(request)
self.assertEqual(gzip_response['ETag'], 'W/"eggs"')
self.assertEqual(gzip_response.headers['ETag'], 'W/"eggs"')
def test_weak_etag_not_modified(self):
"""
@ -929,12 +929,12 @@ class ETagGZipMiddlewareTest(SimpleTestCase):
"""
def get_response(req):
response = HttpResponse(self.compressible_string)
response['ETag'] = 'W/"eggs"'
response.headers['ETag'] = 'W/"eggs"'
return response
request = self.rf.get('/', HTTP_ACCEPT_ENCODING='gzip, deflate')
gzip_response = GZipMiddleware(get_response)(request)
self.assertEqual(gzip_response['ETag'], 'W/"eggs"')
self.assertEqual(gzip_response.headers['ETag'], 'W/"eggs"')
def test_etag_match(self):
"""
@ -949,7 +949,7 @@ class ETagGZipMiddlewareTest(SimpleTestCase):
request = self.rf.get('/', HTTP_ACCEPT_ENCODING='gzip, deflate')
response = GZipMiddleware(get_cond_response)(request)
gzip_etag = response['ETag']
gzip_etag = response.headers['ETag']
next_request = self.rf.get('/', HTTP_ACCEPT_ENCODING='gzip, deflate', HTTP_IF_NONE_MATCH=gzip_etag)
next_response = ConditionalGetMiddleware(get_response)(next_request)
self.assertEqual(next_response.status_code, 304)

View File

@ -12,23 +12,26 @@ from django.test import SimpleTestCase
class FileResponseTests(SimpleTestCase):
def test_file_from_disk_response(self):
response = FileResponse(open(__file__, 'rb'))
self.assertEqual(response['Content-Length'], str(os.path.getsize(__file__)))
self.assertIn(response['Content-Type'], ['text/x-python', 'text/plain'])
self.assertEqual(response['Content-Disposition'], 'inline; filename="test_fileresponse.py"')
self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__)))
self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain'])
self.assertEqual(
response.headers['Content-Disposition'],
'inline; filename="test_fileresponse.py"',
)
response.close()
def test_file_from_buffer_response(self):
response = FileResponse(io.BytesIO(b'binary content'))
self.assertEqual(response['Content-Length'], '14')
self.assertEqual(response['Content-Type'], 'application/octet-stream')
self.assertEqual(response.headers['Content-Length'], '14')
self.assertEqual(response.headers['Content-Type'], 'application/octet-stream')
self.assertFalse(response.has_header('Content-Disposition'))
self.assertEqual(list(response), [b'binary content'])
def test_file_from_buffer_unnamed_attachment(self):
response = FileResponse(io.BytesIO(b'binary content'), as_attachment=True)
self.assertEqual(response['Content-Length'], '14')
self.assertEqual(response['Content-Type'], 'application/octet-stream')
self.assertEqual(response['Content-Disposition'], 'attachment')
self.assertEqual(response.headers['Content-Length'], '14')
self.assertEqual(response.headers['Content-Type'], 'application/octet-stream')
self.assertEqual(response.headers['Content-Disposition'], 'attachment')
self.assertEqual(list(response), [b'binary content'])
@skipIf(sys.platform == 'win32', "Named pipes are Unix-only.")
@ -47,9 +50,12 @@ class FileResponseTests(SimpleTestCase):
def test_file_from_disk_as_attachment(self):
response = FileResponse(open(__file__, 'rb'), as_attachment=True)
self.assertEqual(response['Content-Length'], str(os.path.getsize(__file__)))
self.assertIn(response['Content-Type'], ['text/x-python', 'text/plain'])
self.assertEqual(response['Content-Disposition'], 'attachment; filename="test_fileresponse.py"')
self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__)))
self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain'])
self.assertEqual(
response.headers['Content-Disposition'],
'attachment; filename="test_fileresponse.py"',
)
response.close()
def test_compressed_response(self):
@ -67,7 +73,7 @@ class FileResponseTests(SimpleTestCase):
with self.subTest(ext=extension):
with tempfile.NamedTemporaryFile(suffix=extension) as tmp:
response = FileResponse(tmp)
self.assertEqual(response['Content-Type'], mimetype)
self.assertEqual(response.headers['Content-Type'], mimetype)
self.assertFalse(response.has_header('Content-Encoding'))
def test_unicode_attachment(self):
@ -75,8 +81,11 @@ class FileResponseTests(SimpleTestCase):
ContentFile(b'binary content', name="祝您平安.odt"), as_attachment=True,
content_type='application/vnd.oasis.opendocument.text',
)
self.assertEqual(response['Content-Type'], 'application/vnd.oasis.opendocument.text')
self.assertEqual(
response['Content-Disposition'],
response.headers['Content-Type'],
'application/vnd.oasis.opendocument.text',
)
self.assertEqual(
response.headers['Content-Disposition'],
"attachment; filename*=utf-8''%E7%A5%9D%E6%82%A8%E5%B9%B3%E5%AE%89.odt"
)

View File

@ -39,12 +39,12 @@ class HttpResponseBaseTests(SimpleTestCase):
"""
r = HttpResponseBase()
r['Header'] = 'Value'
r.headers['Header'] = 'Value'
r.setdefault('header', 'changed')
self.assertEqual(r['header'], 'Value')
self.assertEqual(r.headers['header'], 'Value')
r.setdefault('x-header', 'DefaultValue')
self.assertEqual(r['X-Header'], 'DefaultValue')
self.assertEqual(r.headers['X-Header'], 'DefaultValue')
class HttpResponseTests(SimpleTestCase):
@ -92,7 +92,7 @@ class HttpResponseTests(SimpleTestCase):
response = HttpResponse(charset=ISO88591)
self.assertEqual(response.charset, ISO88591)
self.assertEqual(response['Content-Type'], 'text/html; charset=%s' % ISO88591)
self.assertEqual(response.headers['Content-Type'], 'text/html; charset=%s' % ISO88591)
response = HttpResponse(content_type='text/plain; charset=%s' % UTF8, charset=ISO88591)
self.assertEqual(response.charset, ISO88591)
@ -134,7 +134,7 @@ class HttpResponseTests(SimpleTestCase):
def test_repr_no_content_type(self):
response = HttpResponse(status=204)
del response['Content-Type']
del response.headers['Content-Type']
self.assertEqual(repr(response), '<HttpResponse status_code=204>')
def test_wrap_textiowrapper(self):

View File

@ -781,7 +781,7 @@ class SessionMiddlewareTests(TestCase):
)
# SessionMiddleware sets 'Vary: Cookie' to prevent the 'Set-Cookie'
# from being cached.
self.assertEqual(response['Vary'], 'Cookie')
self.assertEqual(response.headers['Vary'], 'Cookie')
@override_settings(SESSION_COOKIE_DOMAIN='.example.local', SESSION_COOKIE_PATH='/example/')
def test_session_delete_on_end_with_custom_domain_and_path(self):
@ -826,7 +826,7 @@ class SessionMiddlewareTests(TestCase):
# A cookie should not be set.
self.assertEqual(response.cookies, {})
# The session is accessed so "Vary: Cookie" should be set.
self.assertEqual(response['Vary'], 'Cookie')
self.assertEqual(response.headers['Vary'], 'Cookie')
def test_empty_session_saved(self):
"""
@ -849,7 +849,7 @@ class SessionMiddlewareTests(TestCase):
'Set-Cookie: sessionid=%s' % request.session.session_key,
str(response.cookies)
)
self.assertEqual(response['Vary'], 'Cookie')
self.assertEqual(response.headers['Vary'], 'Cookie')
# Empty the session data.
del request.session['foo']
@ -866,7 +866,7 @@ class SessionMiddlewareTests(TestCase):
'Set-Cookie: sessionid=%s' % request.session.session_key,
str(response.cookies)
)
self.assertEqual(response['Vary'], 'Cookie')
self.assertEqual(response.headers['Vary'], 'Cookie')
class CookieSessionTests(SessionTestsMixin, SimpleTestCase):

View File

@ -9,7 +9,7 @@ class RenderTests(SimpleTestCase):
response = self.client.get('/render/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'FOO.BAR../render/\n')
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8')
self.assertEqual(response.headers['Content-Type'], 'text/html; charset=utf-8')
self.assertFalse(hasattr(response.context.request, 'current_app'))
def test_render_with_multiple_templates(self):
@ -21,7 +21,7 @@ class RenderTests(SimpleTestCase):
response = self.client.get('/render/content_type/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'FOO.BAR../render/content_type/\n')
self.assertEqual(response['Content-Type'], 'application/x-rendertest')
self.assertEqual(response.headers['Content-Type'], 'application/x-rendertest')
def test_render_with_status(self):
response = self.client.get('/render/status/')

View File

@ -56,4 +56,4 @@ class GenericViewsSitemapTests(SitemapTestsBase):
</urlset>
""" % (self.base_url, test_model.pk)
self.assertXMLEqual(response.content.decode(), expected_content)
self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 10:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Wed, 13 Mar 2013 10:00:00 GMT')

View File

@ -116,14 +116,14 @@ class HTTPSitemapTests(SitemapTestsBase):
def test_sitemap_last_modified(self):
"Last-Modified header is set correctly"
response = self.client.get('/lastmod/sitemap.xml')
self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 10:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Wed, 13 Mar 2013 10:00:00 GMT')
def test_sitemap_last_modified_date(self):
"""
The Last-Modified header should be support dates (without time).
"""
response = self.client.get('/lastmod/date-sitemap.xml')
self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 00:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Wed, 13 Mar 2013 00:00:00 GMT')
def test_sitemap_last_modified_tz(self):
"""
@ -131,7 +131,7 @@ class HTTPSitemapTests(SitemapTestsBase):
to GMT.
"""
response = self.client.get('/lastmod/tz-sitemap.xml')
self.assertEqual(response['Last-Modified'], 'Wed, 13 Mar 2013 15:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Wed, 13 Mar 2013 15:00:00 GMT')
def test_sitemap_last_modified_missing(self):
"Last-Modified header is missing when sitemap has no lastmod"
@ -165,7 +165,7 @@ class HTTPSitemapTests(SitemapTestsBase):
Test sitemaps are sorted by lastmod in ascending order.
"""
response = self.client.get('/lastmod-sitemaps/ascending.xml')
self.assertEqual(response['Last-Modified'], 'Sat, 20 Apr 2013 05:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Sat, 20 Apr 2013 05:00:00 GMT')
def test_sitemaps_lastmod_descending(self):
"""
@ -173,7 +173,7 @@ class HTTPSitemapTests(SitemapTestsBase):
Test sitemaps are sorted by lastmod in descending order.
"""
response = self.client.get('/lastmod-sitemaps/descending.xml')
self.assertEqual(response['Last-Modified'], 'Sat, 20 Apr 2013 05:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Sat, 20 Apr 2013 05:00:00 GMT')
@override_settings(USE_I18N=True, USE_L10N=True)
def test_localized_priority(self):
@ -243,10 +243,10 @@ class HTTPSitemapTests(SitemapTestsBase):
def test_x_robots_sitemap(self):
response = self.client.get('/simple/index.xml')
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')
self.assertEqual(response.headers['X-Robots-Tag'], 'noindex, noodp, noarchive')
response = self.client.get('/simple/sitemap.xml')
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')
self.assertEqual(response.headers['X-Robots-Tag'], 'noindex, noodp, noarchive')
def test_empty_sitemap(self):
response = self.client.get('/empty/sitemap.xml')

View File

@ -421,14 +421,14 @@ class SyndicationFeedTest(FeedTestCase):
Tests the Last-Modified header with naive publication dates.
"""
response = self.client.get('/syndication/naive-dates/')
self.assertEqual(response['Last-Modified'], 'Tue, 26 Mar 2013 01:00:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Tue, 26 Mar 2013 01:00:00 GMT')
def test_feed_last_modified_time(self):
"""
Tests the Last-Modified header with aware publication dates.
"""
response = self.client.get('/syndication/aware-dates/')
self.assertEqual(response['Last-Modified'], 'Mon, 25 Mar 2013 19:18:00 GMT')
self.assertEqual(response.headers['Last-Modified'], 'Mon, 25 Mar 2013 19:18:00 GMT')
# No last-modified when feed has no item_pubdate
response = self.client.get('/syndication/no_pubdate/')

View File

@ -122,13 +122,13 @@ class SimpleTemplateResponseTest(SimpleTestCase):
def test_kwargs(self):
response = self._response(content_type='application/json', status=504, charset='ascii')
self.assertEqual(response['content-type'], 'application/json')
self.assertEqual(response.headers['content-type'], 'application/json')
self.assertEqual(response.status_code, 504)
self.assertEqual(response.charset, 'ascii')
def test_args(self):
response = SimpleTemplateResponse('', {}, 'application/json', 504)
self.assertEqual(response['content-type'], 'application/json')
self.assertEqual(response.headers['content-type'], 'application/json')
self.assertEqual(response.status_code, 504)
@require_jinja2
@ -175,7 +175,7 @@ class SimpleTemplateResponseTest(SimpleTestCase):
unpickled_response = pickle.loads(pickled_response)
self.assertEqual(unpickled_response.content, response.content)
self.assertEqual(unpickled_response['content-type'], response['content-type'])
self.assertEqual(unpickled_response.headers['content-type'], response.headers['content-type'])
self.assertEqual(unpickled_response.status_code, response.status_code)
# ...and the unpickled response doesn't have the
@ -249,13 +249,13 @@ class TemplateResponseTest(SimpleTestCase):
def test_kwargs(self):
response = self._response(content_type='application/json', status=504)
self.assertEqual(response['content-type'], 'application/json')
self.assertEqual(response.headers['content-type'], 'application/json')
self.assertEqual(response.status_code, 504)
def test_args(self):
response = TemplateResponse(self.factory.get('/'), '', {},
'application/json', 504)
self.assertEqual(response['content-type'], 'application/json')
self.assertEqual(response.headers['content-type'], 'application/json')
self.assertEqual(response.status_code, 504)
@require_jinja2
@ -287,7 +287,7 @@ class TemplateResponseTest(SimpleTestCase):
unpickled_response = pickle.loads(pickled_response)
self.assertEqual(unpickled_response.content, response.content)
self.assertEqual(unpickled_response['content-type'], response['content-type'])
self.assertEqual(unpickled_response.headers['content-type'], response.headers['content-type'])
self.assertEqual(unpickled_response.status_code, response.status_code)
# ...and the unpickled response doesn't have the

View File

@ -159,7 +159,7 @@ class ClientTest(TestCase):
"Check the value of HTTP headers returned in a response"
response = self.client.get("/header_view/")
self.assertEqual(response['X-DJANGO-TEST'], 'Slartibartfast')
self.assertEqual(response.headers['X-DJANGO-TEST'], 'Slartibartfast')
def test_response_attached_request(self):
"""

View File

@ -102,7 +102,7 @@ def json_view(request):
def view_with_header(request):
"A view that has a custom header"
response = HttpResponse()
response['X-DJANGO-TEST'] = 'Slartibartfast'
response.headers['X-DJANGO-TEST'] = 'Slartibartfast'
return response

View File

@ -1210,7 +1210,7 @@ class RequestMethodStringDataTests(SimpleTestCase):
)
for content_type in valid_types:
response = self.client.get('/json_response/', {'content_type': content_type})
self.assertEqual(response['Content-Type'], content_type)
self.assertEqual(response.headers['Content-Type'], content_type)
self.assertEqual(response.json(), {'key': 'value'})
def test_json_multiple_access(self):

View File

@ -1481,7 +1481,7 @@ class NonHTMLResponseExceptionReporterFilter(ExceptionReportTestMixin, LoggingCa
@override_settings(DEBUG=True, ROOT_URLCONF='view_tests.urls')
def test_non_html_response_encoding(self):
response = self.client.get('/raises500/', HTTP_ACCEPT='application/json')
self.assertEqual(response['Content-Type'], 'text/plain; charset=utf-8')
self.assertEqual(response.headers['Content-Type'], 'text/plain; charset=utf-8')
class DecoratorsTests(SimpleTestCase):

View File

@ -249,7 +249,7 @@ class I18NViewTests(SimpleTestCase):
catalog = gettext.translation('djangojs', locale_dir, [lang_code])
trans_txt = catalog.gettext('this is to be translated')
response = self.client.get('/jsi18n/')
self.assertEqual(response['Content-Type'], 'text/javascript; charset="utf-8"')
self.assertEqual(response.headers['Content-Type'], 'text/javascript; charset="utf-8"')
# response content must include a line like:
# "this is to be translated": <value of trans_txt Python variable>
# json.dumps() is used to be able to check Unicode strings.

View File

@ -10,7 +10,7 @@ class JsonResponseTests(SimpleTestCase):
response = self.client.get('/json/response/')
self.assertEqual(response.status_code, 200)
self.assertEqual(
response['content-type'], 'application/json')
response.headers['content-type'], 'application/json')
self.assertEqual(json.loads(response.content.decode()), {
'a': [1, 2, 3],
'foo': {'bar': 'baz'},

View File

@ -29,7 +29,7 @@ class StaticTests(SimpleTestCase):
file_path = path.join(media_dir, filename)
with open(file_path, 'rb') as fp:
self.assertEqual(fp.read(), response_content)
self.assertEqual(len(response_content), int(response['Content-Length']))
self.assertEqual(len(response_content), int(response.headers['Content-Length']))
self.assertEqual(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None))
def test_chunked(self):
@ -44,7 +44,7 @@ class StaticTests(SimpleTestCase):
def test_unknown_mime_type(self):
response = self.client.get('/%s/file.unknown' % self.prefix)
self.assertEqual('application/octet-stream', response['Content-Type'])
self.assertEqual('application/octet-stream', response.headers['Content-Type'])
response.close()
def test_copes_with_empty_path_component(self):
@ -87,7 +87,7 @@ class StaticTests(SimpleTestCase):
response_content = b''.join(response)
with open(path.join(media_dir, file_name), 'rb') as fp:
self.assertEqual(fp.read(), response_content)
self.assertEqual(len(response_content), int(response['Content-Length']))
self.assertEqual(len(response_content), int(response.headers['Content-Length']))
def test_invalid_if_modified_since2(self):
"""Handle even more bogus If-Modified-Since values gracefully
@ -102,7 +102,7 @@ class StaticTests(SimpleTestCase):
response_content = b''.join(response)
with open(path.join(media_dir, file_name), 'rb') as fp:
self.assertEqual(fp.read(), response_content)
self.assertEqual(len(response_content), int(response['Content-Length']))
self.assertEqual(len(response_content), int(response.headers['Content-Length']))
def test_404(self):
response = self.client.get('/%s/nonexistent_resource' % self.prefix)