Refs #26447 -- Removed the USE_ETAGS setting per deprecation timeline.
This commit is contained in:
parent
4502489a46
commit
48d57788ee
|
@ -21,11 +21,6 @@ DEBUG = False
|
|||
# on a live site.
|
||||
DEBUG_PROPAGATE_EXCEPTIONS = False
|
||||
|
||||
# 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
|
||||
|
||||
# People who get code error notifications.
|
||||
# In the format [('Full Name', 'email@example.com'), ('Full Name', 'anotheremail@example.com')]
|
||||
ADMINS = []
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import re
|
||||
import warnings
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -7,10 +6,7 @@ from django.core.exceptions import PermissionDenied
|
|||
from django.core.mail import mail_managers
|
||||
from django.http import HttpResponsePermanentRedirect
|
||||
from django.urls import is_valid_path
|
||||
from django.utils.cache import (
|
||||
cc_delim_re, get_conditional_response, set_response_etag,
|
||||
)
|
||||
from django.utils.deprecation import MiddlewareMixin, RemovedInDjango21Warning
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
|
||||
class CommonMiddleware(MiddlewareMixin):
|
||||
|
@ -30,11 +26,6 @@ class CommonMiddleware(MiddlewareMixin):
|
|||
|
||||
This behavior can be customized by subclassing CommonMiddleware and
|
||||
overriding the response_redirect_class attribute.
|
||||
|
||||
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
||||
the entire page content and Not Modified responses will be returned
|
||||
appropriately. USE_ETAGS is deprecated in favor of
|
||||
ConditionalGetMiddleware.
|
||||
"""
|
||||
|
||||
response_redirect_class = HttpResponsePermanentRedirect
|
||||
|
@ -114,23 +105,6 @@ class CommonMiddleware(MiddlewareMixin):
|
|||
if self.should_redirect_with_slash(request):
|
||||
return self.response_redirect_class(self.get_full_path_with_slash(request))
|
||||
|
||||
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'):
|
||||
set_response_etag(response)
|
||||
|
||||
if response.has_header('ETag'):
|
||||
return get_conditional_response(
|
||||
request,
|
||||
etag=response['ETag'],
|
||||
response=response,
|
||||
)
|
||||
# Add the Content-Length header to non-streaming responses if not
|
||||
# already set.
|
||||
if not response.streaming and not response.has_header('Content-Length'):
|
||||
|
@ -138,11 +112,6 @@ class CommonMiddleware(MiddlewareMixin):
|
|||
|
||||
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)
|
||||
|
||||
|
||||
class BrokenLinkEmailsMiddleware(MiddlewareMixin):
|
||||
|
||||
|
|
|
@ -20,12 +20,10 @@ import hashlib
|
|||
import logging
|
||||
import re
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import caches
|
||||
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.http import (
|
||||
http_date, parse_etags, parse_http_date_safe, quote_etag,
|
||||
|
@ -248,18 +246,6 @@ def patch_response_headers(response, cache_timeout=None):
|
|||
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
|
||||
if cache_timeout < 0:
|
||||
cache_timeout = 0 # Can't have max-age negative
|
||||
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):
|
||||
response.add_post_render_callback(set_response_etag)
|
||||
else:
|
||||
response = set_response_etag(response)
|
||||
if not response.has_header('Expires'):
|
||||
response['Expires'] = http_date(time.time() + cache_timeout)
|
||||
patch_cache_control(response, max_age=cache_timeout)
|
||||
|
|
|
@ -61,23 +61,12 @@ Adds a few conveniences for perfectionists:
|
|||
indexer would treat them as separate URLs -- so it's best practice to
|
||||
normalize URLs.
|
||||
|
||||
* Handles ETags based on the :setting:`USE_ETAGS` setting. If
|
||||
:setting:`USE_ETAGS` is set to ``True``, Django will calculate an ETag
|
||||
for each request by MD5-hashing the page content, and it'll take care of
|
||||
sending ``Not Modified`` responses, if appropriate.
|
||||
|
||||
* Sets the ``Content-Length`` header for non-streaming responses.
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
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
|
||||
|
||||
Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
|
||||
|
@ -472,11 +461,6 @@ Here are some hints about the ordering of various Django middleware classes:
|
|||
|
||||
After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
|
||||
|
||||
#. :class:`~django.middleware.http.ConditionalGetMiddleware`
|
||||
|
||||
Before ``CommonMiddleware``: uses its ``ETag`` header when
|
||||
:setting:`USE_ETAGS` = ``True``.
|
||||
|
||||
#. :class:`~django.contrib.sessions.middleware.SessionMiddleware`
|
||||
|
||||
After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
|
||||
|
|
|
@ -2593,23 +2593,6 @@ the correct environment.
|
|||
|
||||
.. _list of time zones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
|
||||
.. setting:: USE_ETAGS
|
||||
|
||||
``USE_ETAGS``
|
||||
-------------
|
||||
|
||||
Default: ``False``
|
||||
|
||||
A boolean that specifies whether to output the ``ETag`` header. This saves
|
||||
bandwidth but slows down performance. This is used by the
|
||||
:class:`~django.middleware.common.CommonMiddleware` and in the :doc:`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
|
||||
|
||||
``USE_I18N``
|
||||
|
@ -3438,7 +3421,6 @@ HTTP
|
|||
* :setting:`SECURE_SSL_HOST`
|
||||
* :setting:`SECURE_SSL_REDIRECT`
|
||||
* :setting:`SIGNING_BACKEND`
|
||||
* :setting:`USE_ETAGS`
|
||||
* :setting:`USE_X_FORWARDED_HOST`
|
||||
* :setting:`USE_X_FORWARDED_PORT`
|
||||
* :setting:`WSGI_APPLICATION`
|
||||
|
|
|
@ -52,7 +52,6 @@ need to distinguish caches by the ``Accept-language`` header.
|
|||
|
||||
Adds some useful headers to the given ``HttpResponse`` object:
|
||||
|
||||
* ``ETag``
|
||||
* ``Expires``
|
||||
* ``Cache-Control``
|
||||
|
||||
|
@ -65,11 +64,6 @@ need to distinguish caches by the ``Accept-language`` header.
|
|||
|
||||
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)
|
||||
|
||||
Adds a ``Cache-Control: max-age=0, no-cache, no-store, must-revalidate``
|
||||
|
|
|
@ -251,3 +251,6 @@ how to remove usage of these features.
|
|||
as the first positional argument.
|
||||
|
||||
* The ``django.db.models.permalink()`` decorator is removed.
|
||||
|
||||
* The ``USE_ETAGS`` setting is removed. ``CommonMiddleware`` and
|
||||
``django.utils.cache.patch_response_headers()`` no longer set ETags.
|
||||
|
|
|
@ -25,14 +25,12 @@ from django.core.files import temp as tempfile
|
|||
from django.forms.utils import ErrorList
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import (
|
||||
SimpleTestCase, TestCase, ignore_warnings, modify_settings,
|
||||
override_settings, skipUnlessDBFeature,
|
||||
TestCase, modify_settings, override_settings, skipUnlessDBFeature,
|
||||
)
|
||||
from django.test.utils import override_script_prefix, patch_logger
|
||||
from django.urls import NoReverseMatch, resolve, reverse
|
||||
from django.utils import formats, translation
|
||||
from django.utils.cache import get_max_age
|
||||
from django.utils.deprecation import RemovedInDjango21Warning
|
||||
from django.utils.encoding import force_bytes, force_text, iri_to_uri
|
||||
from django.utils.html import escape
|
||||
from django.utils.http import urlencode
|
||||
|
@ -5809,22 +5807,6 @@ class InlineAdminViewOnSiteTest(TestCase):
|
|||
self.assertContains(response, '"/worker_inline/%s/%s/"' % (self.w1.surname, self.w1.name))
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='admin_views.urls')
|
||||
class TestETagWithAdminView(SimpleTestCase):
|
||||
# The admin is compatible with ETags (#16003).
|
||||
|
||||
def test_admin(self):
|
||||
with self.settings(USE_ETAGS=False):
|
||||
response = self.client.get(reverse('admin:index'))
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertFalse(response.has_header('ETag'))
|
||||
|
||||
with self.settings(USE_ETAGS=True), ignore_warnings(category=RemovedInDjango21Warning):
|
||||
response = self.client.get(reverse('admin:index'))
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertTrue(response.has_header('ETag'))
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='admin_views.urls')
|
||||
class GetFormsetsWithInlinesArgumentTest(TestCase):
|
||||
"""
|
||||
|
|
|
@ -32,15 +32,13 @@ from django.template.context_processors import csrf
|
|||
from django.template.response import TemplateResponse
|
||||
from django.test import (
|
||||
RequestFactory, SimpleTestCase, TestCase, TransactionTestCase,
|
||||
ignore_warnings, override_settings,
|
||||
override_settings,
|
||||
)
|
||||
from django.test.signals import setting_changed
|
||||
from django.utils import timezone, translation
|
||||
from django.utils.cache import (
|
||||
get_cache_key, learn_cache_key, patch_cache_control,
|
||||
patch_response_headers, patch_vary_headers,
|
||||
get_cache_key, learn_cache_key, patch_cache_control, patch_vary_headers,
|
||||
)
|
||||
from django.utils.deprecation import RemovedInDjango21Warning
|
||||
from django.views.decorators.cache import cache_page
|
||||
|
||||
from .models import Poll, expensive_calculation
|
||||
|
@ -1838,11 +1836,9 @@ class CacheI18nTest(TestCase):
|
|||
"Cache keys should include the time zone name when time zones are active"
|
||||
)
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning) # USE_ETAGS=True
|
||||
@override_settings(
|
||||
CACHE_MIDDLEWARE_KEY_PREFIX="test",
|
||||
CACHE_MIDDLEWARE_SECONDS=60,
|
||||
USE_ETAGS=True,
|
||||
USE_I18N=True,
|
||||
)
|
||||
def test_middleware(self):
|
||||
|
@ -1884,14 +1880,6 @@ class CacheI18nTest(TestCase):
|
|||
# The cache can be recovered
|
||||
self.assertIsNotNone(get_cache_data)
|
||||
self.assertEqual(get_cache_data.content, en_message.encode())
|
||||
# ETags are used.
|
||||
self.assertTrue(get_cache_data.has_header('ETag'))
|
||||
# ETags can be disabled.
|
||||
with self.settings(USE_ETAGS=False):
|
||||
request._cache_update_cache = True
|
||||
set_cache(request, 'en', en_message)
|
||||
get_cache_data = FetchFromCacheMiddleware().process_request(request)
|
||||
self.assertFalse(get_cache_data.has_header('ETag'))
|
||||
# change the session language and set content
|
||||
request = self.factory.get(self.path)
|
||||
request._cache_update_cache = True
|
||||
|
@ -1911,7 +1899,6 @@ class CacheI18nTest(TestCase):
|
|||
@override_settings(
|
||||
CACHE_MIDDLEWARE_KEY_PREFIX="test",
|
||||
CACHE_MIDDLEWARE_SECONDS=60,
|
||||
USE_ETAGS=True,
|
||||
)
|
||||
def test_middleware_doesnt_cache_streaming_response(self):
|
||||
request = self.factory.get(self.path)
|
||||
|
@ -2232,27 +2219,6 @@ class TestWithTemplateResponse(SimpleTestCase):
|
|||
'0f1c2d56633c943073c4569d9a9502fe.d41d8cd98f00b204e9800998ecf8427e'
|
||||
)
|
||||
|
||||
@override_settings(USE_ETAGS=False)
|
||||
def test_without_etag(self):
|
||||
template = engines['django'].from_string("This is a test")
|
||||
response = TemplateResponse(HttpRequest(), template)
|
||||
self.assertFalse(response.has_header('ETag'))
|
||||
patch_response_headers(response)
|
||||
self.assertFalse(response.has_header('ETag'))
|
||||
response = response.render()
|
||||
self.assertFalse(response.has_header('ETag'))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_with_etag(self):
|
||||
template = engines['django'].from_string("This is a test")
|
||||
response = TemplateResponse(HttpRequest(), template)
|
||||
self.assertFalse(response.has_header('ETag'))
|
||||
patch_response_headers(response)
|
||||
self.assertFalse(response.has_header('ETag'))
|
||||
response = response.render()
|
||||
self.assertTrue(response.has_header('ETag'))
|
||||
|
||||
|
||||
class TestMakeTemplateFragmentKey(SimpleTestCase):
|
||||
def test_without_vary_on(self):
|
||||
|
|
|
@ -18,10 +18,7 @@ from django.middleware.common import (
|
|||
)
|
||||
from django.middleware.gzip import GZipMiddleware
|
||||
from django.middleware.http import ConditionalGetMiddleware
|
||||
from django.test import (
|
||||
RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
|
||||
)
|
||||
from django.utils.deprecation import RemovedInDjango21Warning
|
||||
from django.test import RequestFactory, SimpleTestCase, override_settings
|
||||
|
||||
int2byte = struct.Struct(">B").pack
|
||||
|
||||
|
@ -265,57 +262,6 @@ class CommonMiddlewareTest(SimpleTestCase):
|
|||
self.assertEqual(r.status_code, 301)
|
||||
self.assertEqual(r.url, 'http://www.testserver/customurlconf/slash/')
|
||||
|
||||
# ETag + If-Not-Modified support tests
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_etag(self):
|
||||
req = HttpRequest()
|
||||
res = HttpResponse('content')
|
||||
self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_etag_streaming_response(self):
|
||||
req = HttpRequest()
|
||||
res = StreamingHttpResponse(['content'])
|
||||
res['ETag'] = 'tomatoes'
|
||||
self.assertEqual(CommonMiddleware().process_response(req, res).get('ETag'), 'tomatoes')
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_no_etag_streaming_response(self):
|
||||
req = HttpRequest()
|
||||
res = StreamingHttpResponse(['content'])
|
||||
self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_no_etag_no_store_cache(self):
|
||||
req = HttpRequest()
|
||||
res = HttpResponse('content')
|
||||
res['Cache-Control'] = 'No-Cache, No-Store, Max-age=0'
|
||||
self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_etag_extended_cache_control(self):
|
||||
req = HttpRequest()
|
||||
res = HttpResponse('content')
|
||||
res['Cache-Control'] = 'my-directive="my-no-store"'
|
||||
self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
def test_if_none_match(self):
|
||||
first_req = HttpRequest()
|
||||
first_res = CommonMiddleware().process_response(first_req, HttpResponse('content'))
|
||||
second_req = HttpRequest()
|
||||
second_req.method = 'GET'
|
||||
second_req.META['HTTP_IF_NONE_MATCH'] = first_res['ETag']
|
||||
second_res = CommonMiddleware().process_response(second_req, HttpResponse('content'))
|
||||
self.assertEqual(second_res.status_code, 304)
|
||||
|
||||
# Tests for the Content-Length header
|
||||
|
||||
def test_content_length_header_added(self):
|
||||
|
@ -855,8 +801,6 @@ class GZipMiddlewareTest(SimpleTestCase):
|
|||
self.assertEqual(self.get_mtime(r2.content), 0)
|
||||
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
@override_settings(USE_ETAGS=True)
|
||||
class ETagGZipMiddlewareTest(SimpleTestCase):
|
||||
"""
|
||||
ETags are handled properly by GZipMiddleware.
|
||||
|
|
Loading…
Reference in New Issue