Fixed #26447 -- Deprecated settings.USE_ETAGS in favor of ConditionalGetMiddleware.
This commit is contained in:
parent
46a3d7604e
commit
a840710e1e
|
@ -23,6 +23,8 @@ DEBUG = False
|
||||||
DEBUG_PROPAGATE_EXCEPTIONS = False
|
DEBUG_PROPAGATE_EXCEPTIONS = False
|
||||||
|
|
||||||
# Whether to use the "ETag" header. This saves bandwidth but slows down performance.
|
# Whether to use the "ETag" header. This saves bandwidth but slows down performance.
|
||||||
|
# Deprecated (RemovedInDjango21Warning) in favor of ConditionalGetMiddleware
|
||||||
|
# which sets the ETag regardless of this setting.
|
||||||
USE_ETAGS = False
|
USE_ETAGS = False
|
||||||
|
|
||||||
# People who get code error notifications.
|
# People who get code error notifications.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import re
|
import re
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django import http
|
from django import http
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -8,7 +9,7 @@ from django.urls import is_valid_path
|
||||||
from django.utils.cache import (
|
from django.utils.cache import (
|
||||||
cc_delim_re, get_conditional_response, set_response_etag,
|
cc_delim_re, get_conditional_response, set_response_etag,
|
||||||
)
|
)
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
from django.utils.deprecation import MiddlewareMixin, RemovedInDjango21Warning
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
from django.utils.six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
@ -34,7 +35,8 @@ class CommonMiddleware(MiddlewareMixin):
|
||||||
|
|
||||||
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
||||||
the entire page content and Not Modified responses will be returned
|
the entire page content and Not Modified responses will be returned
|
||||||
appropriately.
|
appropriately. USE_ETAGS is deprecated in favor of
|
||||||
|
ConditionalGetMiddleware.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
response_redirect_class = http.HttpResponsePermanentRedirect
|
response_redirect_class = http.HttpResponsePermanentRedirect
|
||||||
|
@ -115,6 +117,13 @@ class CommonMiddleware(MiddlewareMixin):
|
||||||
return self.response_redirect_class(self.get_full_path_with_slash(request))
|
return self.response_redirect_class(self.get_full_path_with_slash(request))
|
||||||
|
|
||||||
if settings.USE_ETAGS and self.needs_etag(response):
|
if settings.USE_ETAGS and self.needs_etag(response):
|
||||||
|
warnings.warn(
|
||||||
|
"The USE_ETAGS setting is deprecated in favor of "
|
||||||
|
"ConditionalGetMiddleware which sets the ETag regardless of "
|
||||||
|
"the setting. CommonMiddleware won't do ETag processing in "
|
||||||
|
"Django 2.1.",
|
||||||
|
RemovedInDjango21Warning
|
||||||
|
)
|
||||||
if not response.has_header('ETag'):
|
if not response.has_header('ETag'):
|
||||||
set_response_etag(response)
|
set_response_etag(response)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
from django.utils.cache import get_conditional_response
|
from django.utils.cache import (
|
||||||
|
cc_delim_re, get_conditional_response, set_response_etag,
|
||||||
|
)
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
from django.utils.http import http_date, parse_http_date_safe
|
from django.utils.http import http_date, parse_http_date_safe
|
||||||
|
|
||||||
|
@ -7,7 +9,8 @@ class ConditionalGetMiddleware(MiddlewareMixin):
|
||||||
"""
|
"""
|
||||||
Handles conditional GET operations. If the response has an ETag or
|
Handles conditional GET operations. If the response has an ETag or
|
||||||
Last-Modified header, and the request has If-None-Match or
|
Last-Modified header, and the request has If-None-Match or
|
||||||
If-Modified-Since, the response is replaced by an HttpNotModified.
|
If-Modified-Since, the response is replaced by an HttpNotModified. An ETag
|
||||||
|
header is added if needed.
|
||||||
|
|
||||||
Also sets the Date and Content-Length response-headers.
|
Also sets the Date and Content-Length response-headers.
|
||||||
"""
|
"""
|
||||||
|
@ -16,6 +19,9 @@ class ConditionalGetMiddleware(MiddlewareMixin):
|
||||||
if not response.streaming and not response.has_header('Content-Length'):
|
if not response.streaming and not response.has_header('Content-Length'):
|
||||||
response['Content-Length'] = str(len(response.content))
|
response['Content-Length'] = str(len(response.content))
|
||||||
|
|
||||||
|
if self.needs_etag(response) and not response.has_header('ETag'):
|
||||||
|
set_response_etag(response)
|
||||||
|
|
||||||
etag = response.get('ETag')
|
etag = response.get('ETag')
|
||||||
last_modified = response.get('Last-Modified')
|
last_modified = response.get('Last-Modified')
|
||||||
if last_modified:
|
if last_modified:
|
||||||
|
@ -30,3 +36,10 @@ class ConditionalGetMiddleware(MiddlewareMixin):
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def needs_etag(self, response):
|
||||||
|
"""
|
||||||
|
Return True if an ETag header should be added to response.
|
||||||
|
"""
|
||||||
|
cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
|
||||||
|
return all(header.lower() != 'no-store' for header in cache_control_headers)
|
||||||
|
|
|
@ -22,10 +22,12 @@ import hashlib
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import caches
|
from django.core.cache import caches
|
||||||
from django.http import HttpResponse, HttpResponseNotModified
|
from django.http import HttpResponse, HttpResponseNotModified
|
||||||
|
from django.utils.deprecation import RemovedInDjango21Warning
|
||||||
from django.utils.encoding import force_bytes, force_text, iri_to_uri
|
from django.utils.encoding import force_bytes, force_text, iri_to_uri
|
||||||
from django.utils.http import (
|
from django.utils.http import (
|
||||||
http_date, parse_etags, parse_http_date_safe, quote_etag,
|
http_date, parse_etags, parse_http_date_safe, quote_etag,
|
||||||
|
@ -242,6 +244,13 @@ def patch_response_headers(response, cache_timeout=None):
|
||||||
if cache_timeout < 0:
|
if cache_timeout < 0:
|
||||||
cache_timeout = 0 # Can't have max-age negative
|
cache_timeout = 0 # Can't have max-age negative
|
||||||
if settings.USE_ETAGS and not response.has_header('ETag'):
|
if settings.USE_ETAGS and not response.has_header('ETag'):
|
||||||
|
warnings.warn(
|
||||||
|
"The USE_ETAGS setting is deprecated in favor of "
|
||||||
|
"ConditionalGetMiddleware which sets the ETag regardless of the "
|
||||||
|
"setting. patch_response_headers() won't do ETag processing in "
|
||||||
|
"Django 2.1.",
|
||||||
|
RemovedInDjango21Warning
|
||||||
|
)
|
||||||
if hasattr(response, 'render') and callable(response.render):
|
if hasattr(response, 'render') and callable(response.render):
|
||||||
response.add_post_render_callback(set_response_etag)
|
response.add_post_render_callback(set_response_etag)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -43,6 +43,9 @@ details on these changes.
|
||||||
|
|
||||||
* The ``django.db.models.permalink()`` decorator will be removed.
|
* The ``django.db.models.permalink()`` decorator will be removed.
|
||||||
|
|
||||||
|
* The ``USE_ETAGS`` setting will be removed. ``CommonMiddleware`` and
|
||||||
|
``django.utils.cache.patch_response_headers()`` will no longer set ETags.
|
||||||
|
|
||||||
.. _deprecation-removed-in-2.0:
|
.. _deprecation-removed-in-2.0:
|
||||||
|
|
||||||
2.0
|
2.0
|
||||||
|
|
|
@ -72,6 +72,12 @@ Adds a few conveniences for perfectionists:
|
||||||
|
|
||||||
Older versions didn't set the ``Content-Length`` header.
|
Older versions didn't set the ``Content-Length`` header.
|
||||||
|
|
||||||
|
.. deprecated:: 1.11
|
||||||
|
|
||||||
|
The :setting:`USE_ETAGS` setting is deprecated in favor of using
|
||||||
|
:class:`~django.middleware.http.ConditionalGetMiddleware` for ETag
|
||||||
|
processing.
|
||||||
|
|
||||||
.. attribute:: CommonMiddleware.response_redirect_class
|
.. attribute:: CommonMiddleware.response_redirect_class
|
||||||
|
|
||||||
Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
|
Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
|
||||||
|
@ -166,13 +172,18 @@ Conditional GET middleware
|
||||||
|
|
||||||
.. class:: ConditionalGetMiddleware
|
.. class:: ConditionalGetMiddleware
|
||||||
|
|
||||||
Handles conditional GET operations. If the response has a ``ETag`` or
|
Handles conditional GET operations. If the response doesn't have an ``ETag``
|
||||||
|
header, the middleware adds one if needed. If the response has a ``ETag`` or
|
||||||
``Last-Modified`` header, and the request has ``If-None-Match`` or
|
``Last-Modified`` header, and the request has ``If-None-Match`` or
|
||||||
``If-Modified-Since``, the response is replaced by an
|
``If-Modified-Since``, the response is replaced by an
|
||||||
:class:`~django.http.HttpResponseNotModified`.
|
:class:`~django.http.HttpResponseNotModified`.
|
||||||
|
|
||||||
Also sets the ``Date`` and ``Content-Length`` response-headers.
|
Also sets the ``Date`` and ``Content-Length`` response-headers.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.11
|
||||||
|
|
||||||
|
In older versions, the middleware didn't set the ``ETag`` header.
|
||||||
|
|
||||||
Locale middleware
|
Locale middleware
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
@ -2532,6 +2532,11 @@ bandwidth but slows down performance. This is used by the
|
||||||
:class:`~django.middleware.common.CommonMiddleware` and in the :doc:`cache
|
:class:`~django.middleware.common.CommonMiddleware` and in the :doc:`cache
|
||||||
framework </topics/cache>`.
|
framework </topics/cache>`.
|
||||||
|
|
||||||
|
.. deprecated:: 1.11
|
||||||
|
|
||||||
|
This setting is deprecated in favor of using ``ConditionalGetMiddleware``,
|
||||||
|
which sets an ETag regardless of this setting.
|
||||||
|
|
||||||
.. setting:: USE_I18N
|
.. setting:: USE_I18N
|
||||||
|
|
||||||
``USE_I18N``
|
``USE_I18N``
|
||||||
|
|
|
@ -65,6 +65,11 @@ need to distinguish caches by the ``Accept-language`` header.
|
||||||
|
|
||||||
In older versions, the ``Last-Modified`` header was also set.
|
In older versions, the ``Last-Modified`` header was also set.
|
||||||
|
|
||||||
|
.. deprecated:: 1.11
|
||||||
|
|
||||||
|
Since the ``USE_ETAGS`` setting is deprecated, this function won't set
|
||||||
|
the ``ETag`` header when the deprecation ends in Django 2.1.
|
||||||
|
|
||||||
.. function:: add_never_cache_headers(response)
|
.. function:: add_never_cache_headers(response)
|
||||||
|
|
||||||
Adds a ``Cache-Control: max-age=0, no-cache, no-store, must-revalidate``
|
Adds a ``Cache-Control: max-age=0, no-cache, no-store, must-revalidate``
|
||||||
|
|
|
@ -327,6 +327,9 @@ Requests and Responses
|
||||||
* Added the :setting:`SECURE_HSTS_PRELOAD` setting to allow appending the
|
* Added the :setting:`SECURE_HSTS_PRELOAD` setting to allow appending the
|
||||||
``preload`` directive to the ``Strict-Transport-Security`` header.
|
``preload`` directive to the ``Strict-Transport-Security`` header.
|
||||||
|
|
||||||
|
* :class:`~django.middleware.http.ConditionalGetMiddleware` now adds the
|
||||||
|
``ETag`` header to responses.
|
||||||
|
|
||||||
Serialization
|
Serialization
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -633,3 +636,9 @@ Miscellaneous
|
||||||
* :func:`~django.contrib.auth.authenticate` now passes a ``request`` argument
|
* :func:`~django.contrib.auth.authenticate` now passes a ``request`` argument
|
||||||
to the ``authenticate()`` method of authentication backends. Support for
|
to the ``authenticate()`` method of authentication backends. Support for
|
||||||
methods that don't accept ``request`` will be removed in Django 2.1.
|
methods that don't accept ``request`` will be removed in Django 2.1.
|
||||||
|
|
||||||
|
* The ``USE_ETAGS`` setting is deprecated in favor of
|
||||||
|
:class:`~django.middleware.http.ConditionalGetMiddleware` which now adds the
|
||||||
|
``ETag`` header to responses regardless of the setting. ``CommonMiddleware``
|
||||||
|
and ``django.utils.cache.patch_response_headers()`` will no longer set ETags
|
||||||
|
when the deprecation ends.
|
||||||
|
|
|
@ -11,7 +11,7 @@ used for all HTTP methods (``POST``, ``PUT``, ``DELETE``, etc.).
|
||||||
For each page (response) that Django sends back from a view, it might provide
|
For each page (response) that Django sends back from a view, it might provide
|
||||||
two HTTP headers: the ``ETag`` header and the ``Last-Modified`` header. These
|
two HTTP headers: the ``ETag`` header and the ``Last-Modified`` header. These
|
||||||
headers are optional on HTTP responses. They can be set by your view function,
|
headers are optional on HTTP responses. They can be set by your view function,
|
||||||
or you can rely on the :class:`~django.middleware.common.CommonMiddleware`
|
or you can rely on the :class:`~django.middleware.http.ConditionalGetMiddleware`
|
||||||
middleware to set the ``ETag`` header.
|
middleware to set the ``ETag`` header.
|
||||||
|
|
||||||
When the client next requests the same resource, it might send along a header
|
When the client next requests the same resource, it might send along a header
|
||||||
|
@ -189,17 +189,14 @@ every time.
|
||||||
Comparison with middleware conditional processing
|
Comparison with middleware conditional processing
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
You may notice that Django already provides simple and straightforward
|
Django provides simple and straightforward conditional ``GET`` handling via
|
||||||
conditional ``GET`` handling via the
|
:class:`django.middleware.http.ConditionalGetMiddleware`. While being easy to
|
||||||
:class:`django.middleware.http.ConditionalGetMiddleware` and
|
use and suitable for many situations, the middleware has limitations for
|
||||||
:class:`~django.middleware.common.CommonMiddleware`. While certainly being
|
advanced usage:
|
||||||
easy to use and suitable for many situations, those pieces of middleware
|
|
||||||
functionality have limitations for advanced usage:
|
|
||||||
|
|
||||||
* They are applied globally to all views in your project
|
* It's applied globally to all views in your project.
|
||||||
* They don't save you from generating the response itself, which may be
|
* It doesn't save you from generating the response, which may be expensive.
|
||||||
expensive
|
* It's only appropriate for HTTP ``GET`` requests.
|
||||||
* They are only appropriate for HTTP ``GET`` requests.
|
|
||||||
|
|
||||||
You should choose the most appropriate tool for your particular problem here.
|
You should choose the most appropriate tool for your particular problem here.
|
||||||
If you have a way to compute ETags and modification times quickly and if some
|
If you have a way to compute ETags and modification times quickly and if some
|
||||||
|
|
|
@ -1372,8 +1372,8 @@ URL::
|
||||||
]
|
]
|
||||||
|
|
||||||
Client-side caching will save bandwidth and make your site load faster. If
|
Client-side caching will save bandwidth and make your site load faster. If
|
||||||
you're using ETags (:setting:`USE_ETAGS = True <USE_ETAGS>`), you're already
|
you're using ETags (:class:`~django.middleware.http.ConditionalGetMiddleware`),
|
||||||
covered. Otherwise, you can apply :ref:`conditional decorators
|
you're already covered. Otherwise, you can apply :ref:`conditional decorators
|
||||||
<conditional-decorators>`. In the following example, the cache is invalidated
|
<conditional-decorators>`. In the following example, the cache is invalidated
|
||||||
whenever you restart your application server::
|
whenever you restart your application server::
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,8 @@ that can help optimize your site's performance. They include:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Adds support for modern browsers to conditionally GET responses based on the
|
Adds support for modern browsers to conditionally GET responses based on the
|
||||||
``ETag`` and ``Last-Modified`` headers.
|
``ETag`` and ``Last-Modified`` headers. It also calculates and sets an ETag if
|
||||||
|
needed.
|
||||||
|
|
||||||
:class:`~django.middleware.gzip.GZipMiddleware`
|
:class:`~django.middleware.gzip.GZipMiddleware`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -35,7 +35,9 @@ from django.urls import NoReverseMatch, resolve, reverse
|
||||||
from django.utils import formats, six, translation
|
from django.utils import formats, six, translation
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.cache import get_max_age
|
from django.utils.cache import get_max_age
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
from django.utils.deprecation import (
|
||||||
|
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||||
|
)
|
||||||
from django.utils.encoding import force_bytes, force_text, iri_to_uri
|
from django.utils.encoding import force_bytes, force_text, iri_to_uri
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
|
@ -6074,7 +6076,7 @@ class TestETagWithAdminView(SimpleTestCase):
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertFalse(response.has_header('ETag'))
|
self.assertFalse(response.has_header('ETag'))
|
||||||
|
|
||||||
with self.settings(USE_ETAGS=True):
|
with self.settings(USE_ETAGS=True), ignore_warnings(category=RemovedInDjango21Warning):
|
||||||
response = self.client.get(reverse('admin:index'))
|
response = self.client.get(reverse('admin:index'))
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertTrue(response.has_header('ETag'))
|
self.assertTrue(response.has_header('ETag'))
|
||||||
|
|
|
@ -33,8 +33,8 @@ from django.template import engines
|
||||||
from django.template.context_processors import csrf
|
from django.template.context_processors import csrf
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.test import (
|
from django.test import (
|
||||||
RequestFactory, SimpleTestCase, TestCase, TransactionTestCase, mock,
|
RequestFactory, SimpleTestCase, TestCase, TransactionTestCase,
|
||||||
override_settings,
|
ignore_warnings, mock, override_settings,
|
||||||
)
|
)
|
||||||
from django.test.signals import setting_changed
|
from django.test.signals import setting_changed
|
||||||
from django.utils import six, timezone, translation
|
from django.utils import six, timezone, translation
|
||||||
|
@ -1856,6 +1856,7 @@ class CacheI18nTest(TestCase):
|
||||||
"Cache keys should include the time zone name when time zones are active"
|
"Cache keys should include the time zone name when time zones are active"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning) # USE_ETAGS=True
|
||||||
@override_settings(
|
@override_settings(
|
||||||
CACHE_MIDDLEWARE_KEY_PREFIX="test",
|
CACHE_MIDDLEWARE_KEY_PREFIX="test",
|
||||||
CACHE_MIDDLEWARE_SECONDS=60,
|
CACHE_MIDDLEWARE_SECONDS=60,
|
||||||
|
@ -2262,6 +2263,7 @@ class TestWithTemplateResponse(SimpleTestCase):
|
||||||
response = response.render()
|
response = response.render()
|
||||||
self.assertFalse(response.has_header('ETag'))
|
self.assertFalse(response.has_header('ETag'))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_with_etag(self):
|
def test_with_etag(self):
|
||||||
template = engines['django'].from_string("This is a test")
|
template = engines['django'].from_string("This is a test")
|
||||||
|
|
|
@ -20,8 +20,11 @@ from django.middleware.common import (
|
||||||
)
|
)
|
||||||
from django.middleware.gzip import GZipMiddleware
|
from django.middleware.gzip import GZipMiddleware
|
||||||
from django.middleware.http import ConditionalGetMiddleware
|
from django.middleware.http import ConditionalGetMiddleware
|
||||||
from django.test import RequestFactory, SimpleTestCase, override_settings
|
from django.test import (
|
||||||
|
RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
|
||||||
|
)
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
from django.utils.deprecation import RemovedInDjango21Warning
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from django.utils.six.moves import range
|
from django.utils.six.moves import range
|
||||||
from django.utils.six.moves.urllib.parse import quote
|
from django.utils.six.moves.urllib.parse import quote
|
||||||
|
@ -256,12 +259,14 @@ class CommonMiddlewareTest(SimpleTestCase):
|
||||||
|
|
||||||
# ETag + If-Not-Modified support tests
|
# ETag + If-Not-Modified support tests
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_etag(self):
|
def test_etag(self):
|
||||||
req = HttpRequest()
|
req = HttpRequest()
|
||||||
res = HttpResponse('content')
|
res = HttpResponse('content')
|
||||||
self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_etag_streaming_response(self):
|
def test_etag_streaming_response(self):
|
||||||
req = HttpRequest()
|
req = HttpRequest()
|
||||||
|
@ -269,12 +274,14 @@ class CommonMiddlewareTest(SimpleTestCase):
|
||||||
res['ETag'] = 'tomatoes'
|
res['ETag'] = 'tomatoes'
|
||||||
self.assertEqual(CommonMiddleware().process_response(req, res).get('ETag'), 'tomatoes')
|
self.assertEqual(CommonMiddleware().process_response(req, res).get('ETag'), 'tomatoes')
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_no_etag_streaming_response(self):
|
def test_no_etag_streaming_response(self):
|
||||||
req = HttpRequest()
|
req = HttpRequest()
|
||||||
res = StreamingHttpResponse(['content'])
|
res = StreamingHttpResponse(['content'])
|
||||||
self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_no_etag_no_store_cache(self):
|
def test_no_etag_no_store_cache(self):
|
||||||
req = HttpRequest()
|
req = HttpRequest()
|
||||||
|
@ -282,6 +289,7 @@ class CommonMiddlewareTest(SimpleTestCase):
|
||||||
res['Cache-Control'] = 'No-Cache, No-Store, Max-age=0'
|
res['Cache-Control'] = 'No-Cache, No-Store, Max-age=0'
|
||||||
self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_etag_extended_cache_control(self):
|
def test_etag_extended_cache_control(self):
|
||||||
req = HttpRequest()
|
req = HttpRequest()
|
||||||
|
@ -289,6 +297,7 @@ class CommonMiddlewareTest(SimpleTestCase):
|
||||||
res['Cache-Control'] = 'my-directive="my-no-store"'
|
res['Cache-Control'] = 'my-directive="my-no-store"'
|
||||||
self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
def test_if_none_match(self):
|
def test_if_none_match(self):
|
||||||
first_req = HttpRequest()
|
first_req = HttpRequest()
|
||||||
|
@ -502,6 +511,30 @@ class ConditionalGetMiddlewareTest(SimpleTestCase):
|
||||||
|
|
||||||
# Tests for the ETag header
|
# Tests for the ETag header
|
||||||
|
|
||||||
|
def test_middleware_calculates_etag(self):
|
||||||
|
self.assertNotIn('ETag', self.resp)
|
||||||
|
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
|
||||||
|
self.assertEqual(self.resp.status_code, 200)
|
||||||
|
self.assertNotEqual('', self.resp['ETag'])
|
||||||
|
|
||||||
|
def test_middleware_wont_overwrite_etag(self):
|
||||||
|
self.resp['ETag'] = 'eggs'
|
||||||
|
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
|
||||||
|
self.assertEqual(self.resp.status_code, 200)
|
||||||
|
self.assertEqual('eggs', self.resp['ETag'])
|
||||||
|
|
||||||
|
def test_no_etag_streaming_response(self):
|
||||||
|
res = StreamingHttpResponse(['content'])
|
||||||
|
self.assertFalse(ConditionalGetMiddleware().process_response(self.req, res).has_header('ETag'))
|
||||||
|
|
||||||
|
def test_no_etag_no_store_cache(self):
|
||||||
|
self.resp['Cache-Control'] = 'No-Cache, No-Store, Max-age=0'
|
||||||
|
self.assertFalse(ConditionalGetMiddleware().process_response(self.req, self.resp).has_header('ETag'))
|
||||||
|
|
||||||
|
def test_etag_extended_cache_control(self):
|
||||||
|
self.resp['Cache-Control'] = 'my-directive="my-no-store"'
|
||||||
|
self.assertTrue(ConditionalGetMiddleware().process_response(self.req, self.resp).has_header('ETag'))
|
||||||
|
|
||||||
def test_if_none_match_and_no_etag(self):
|
def test_if_none_match_and_no_etag(self):
|
||||||
self.req.META['HTTP_IF_NONE_MATCH'] = 'spam'
|
self.req.META['HTTP_IF_NONE_MATCH'] = 'spam'
|
||||||
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
|
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
|
||||||
|
@ -796,6 +829,7 @@ class GZipMiddlewareTest(SimpleTestCase):
|
||||||
self.assertIsNone(r.get('Content-Encoding'))
|
self.assertIsNone(r.get('Content-Encoding'))
|
||||||
|
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||||
@override_settings(USE_ETAGS=True)
|
@override_settings(USE_ETAGS=True)
|
||||||
class ETagGZipMiddlewareTest(SimpleTestCase):
|
class ETagGZipMiddlewareTest(SimpleTestCase):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue