mirror of https://github.com/django/django.git
Fixed #28104 -- Prevented condition decorator from setting ETag/Last-Modified headers for non-safe requests.
This commit is contained in:
parent
268a646353
commit
37c9b81ebc
|
@ -70,9 +70,9 @@ def condition(etag_func=None, last_modified_func=None):
|
||||||
|
|
||||||
This decorator will either pass control to the wrapped view function or
|
This decorator will either pass control to the wrapped view function or
|
||||||
return an HTTP 304 response (unmodified) or 412 response (precondition
|
return an HTTP 304 response (unmodified) or 412 response (precondition
|
||||||
failed), depending upon the request method. In either case, it will add the
|
failed), depending upon the request method. In either case, the decorator
|
||||||
generated ETag and Last-Modified headers to the response if it doesn't
|
will add the generated ETag and Last-Modified headers to the response if
|
||||||
already have them.
|
the headers aren't already set and if the request's method is safe.
|
||||||
"""
|
"""
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
|
@ -98,11 +98,13 @@ def condition(etag_func=None, last_modified_func=None):
|
||||||
if response is None:
|
if response is None:
|
||||||
response = func(request, *args, **kwargs)
|
response = func(request, *args, **kwargs)
|
||||||
|
|
||||||
# Set relevant headers on the response if they don't already exist.
|
# Set relevant headers on the response if they don't already exist
|
||||||
if res_last_modified and not response.has_header('Last-Modified'):
|
# and if the request method is safe.
|
||||||
response['Last-Modified'] = http_date(res_last_modified)
|
if request.method in ('GET', 'HEAD'):
|
||||||
if res_etag and not response.has_header('ETag'):
|
if res_last_modified and not response.has_header('Last-Modified'):
|
||||||
response['ETag'] = res_etag
|
response['Last-Modified'] = http_date(res_last_modified)
|
||||||
|
if res_etag and not response.has_header('ETag'):
|
||||||
|
response['ETag'] = res_etag
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,10 @@ last time the resource was modified, or ``None`` if the resource doesn't
|
||||||
exist. The function passed to the ``etag`` decorator should return a string
|
exist. The function passed to the ``etag`` decorator should return a string
|
||||||
representing the `ETag`_ for the resource, or ``None`` if it doesn't exist.
|
representing the `ETag`_ for the resource, or ``None`` if it doesn't exist.
|
||||||
|
|
||||||
|
The decorator sets the ``ETag`` and ``Last-Modified`` headers on the response
|
||||||
|
if they are not already set by the view and if the request's method is safe
|
||||||
|
(``GET`` or ``HEAD``).
|
||||||
|
|
||||||
.. versionchanged:: 1.11
|
.. versionchanged:: 1.11
|
||||||
|
|
||||||
In older versions, the return value from ``etag_func()`` was interpreted as
|
In older versions, the return value from ``etag_func()`` was interpreted as
|
||||||
|
@ -198,6 +202,14 @@ to compute the ETag and last modification values in all situations. In fact,
|
||||||
you **should** use the same functions, so that the same values are returned
|
you **should** use the same functions, so that the same values are returned
|
||||||
every time.
|
every time.
|
||||||
|
|
||||||
|
.. admonition:: Validator headers with non-safe request methods
|
||||||
|
|
||||||
|
The ``condition`` decorator only sets validator headers (``ETag`` and
|
||||||
|
``Last-Modified``) for safe HTTP methods, i.e. ``GET`` and ``HEAD``. If you
|
||||||
|
wish to return them in other cases, set them in your view. See
|
||||||
|
:rfc:`7231#section-4.3.4` to learn about the distinction between setting a
|
||||||
|
validator header in response to requests made with ``PUT`` versus ``POST``.
|
||||||
|
|
||||||
Comparison with middleware conditional processing
|
Comparison with middleware conditional processing
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,14 @@ class ConditionalGet(SimpleTestCase):
|
||||||
def assertFullResponse(self, response, check_last_modified=True, check_etag=True):
|
def assertFullResponse(self, response, check_last_modified=True, check_etag=True):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.content, FULL_RESPONSE.encode())
|
self.assertEqual(response.content, FULL_RESPONSE.encode())
|
||||||
if check_last_modified:
|
if response.request['REQUEST_METHOD'] in ('GET', 'HEAD'):
|
||||||
self.assertEqual(response['Last-Modified'], LAST_MODIFIED_STR)
|
if check_last_modified:
|
||||||
if check_etag:
|
self.assertEqual(response['Last-Modified'], LAST_MODIFIED_STR)
|
||||||
self.assertEqual(response['ETag'], ETAG)
|
if check_etag:
|
||||||
|
self.assertEqual(response['ETag'], ETAG)
|
||||||
|
else:
|
||||||
|
self.assertNotIn('Last-Modified', response)
|
||||||
|
self.assertNotIn('ETag', response)
|
||||||
|
|
||||||
def assertNotModified(self, response):
|
def assertNotModified(self, response):
|
||||||
self.assertEqual(response.status_code, 304)
|
self.assertEqual(response.status_code, 304)
|
||||||
|
|
Loading…
Reference in New Issue