Skip to content

Commit

Permalink
Merge branch 'main' into release/2
Browse files Browse the repository at this point in the history
  • Loading branch information
vsalvino committed Aug 5, 2022
2 parents 64f8f5c + b26be37 commit 05df1ad
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 12 deletions.
5 changes: 5 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ stages:
- script: python -m pip install -r requirements-dev.txt
displayName: 'CR-QC: Install from local repo'

- script: |
cd testproject/
python manage.py makemigrations --check
displayName: 'CR-QC: Check migrations'
- script: pytest ./testproject/
displayName: 'CR-QC: Run unit tests'

Expand Down
19 changes: 19 additions & 0 deletions docs/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
Release Notes
=============


2.1.1
=====

* Fix Django deprecation warnings.

* Previously, the feature to strip cookies was not triggered if the Vary header
contained something other than "Cookie", e.g. ``Vary: Language, Cookie``. This
change properly inspects and rebuilds the Vary header in such cases.


2.1.0
=====

Expand All @@ -24,6 +35,14 @@ Google Analytics, Facebook Pixel, HubSpot, etc.
the 1.x series as needed.


1.2.1
=====

* Previously, the feature to strip cookies was not triggered if the Vary header
contained something other than "Cookie", e.g. ``Vary: Language, Cookie``. This
change properly inspects and rebuilds the Vary header in such cases.


1.2.0
=====

Expand Down
3 changes: 0 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,3 @@ DJANGO_SETTINGS_MODULE = testproject.settings
junit_family = xunit2
addopts = --cov wagtailcache --cov-report html --cov-report xml --junitxml junit/test-results.xml
python_files = tests.py test_*.py
filterwarnings =
ignore
default:::wagtailcache.*
8 changes: 8 additions & 0 deletions testproject/home/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@ def test_client_tracking_cookies_ignore(self):
self.client.cookies["_dataminer"] = "precious data"
self.get_hit(self.page_cachedpage.get_url())

@override_settings(WAGTAIL_CACHE_IGNORE_COOKIES=True)
def test_vary_header_parse(self):
self.get_miss(reverse("vary_view"))
r = self.get_hit(reverse("vary_view"))
# Cookie should have been stripped from the Vary header while preserving
# case and order of the other items.
self.assertEqual(r["Vary"], "A, B, C")

def test_page_restricted(self):
auth_url = "/_util/authenticate_with_password/%d/%d/" % (
self.view_restriction.id,
Expand Down
6 changes: 6 additions & 0 deletions testproject/home/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ def cached_view(request):
@nocache_page
def nocached_view(request):
return HttpResponse("Hello, World!")


def vary_view(request):
r = HttpResponse("Variety is the spice of life.")
r.headers["Vary"] = "A, B, Cookie, C"
return r
2 changes: 0 additions & 2 deletions testproject/testproject/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@

USE_I18N = True

USE_L10N = True

USE_TZ = True


Expand Down
5 changes: 3 additions & 2 deletions testproject/testproject/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
path("django-admin/", admin.site.urls),
path("admin/", include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
path("views/cached-view/", views.cached_view, name="cached_view"),
path("views/nocache-view/", views.nocached_view, name="nocached_view"),
path("views/cached/", views.cached_view, name="cached_view"),
path("views/nocache/", views.nocached_view, name="nocached_view"),
path("views/vary/", views.vary_view, name="vary_view"),
# For anything not caught by a more specific rule above, hand over to
# Wagtail's page serving mechanism. This should be the last pattern in
# the list:
Expand Down
4 changes: 1 addition & 3 deletions wagtailcache/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
release = ["2", "1", "0"]
release = ["2", "1", "1"]
__version__ = "{0}.{1}.{2}".format(release[0], release[1], release[2])
__shortversion__ = "{0}.{1}".format(release[0], release[1])

default_app_config = "wagtailcache.apps.WagtailCacheAppConfig"
33 changes: 31 additions & 2 deletions wagtailcache/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from django.http.response import HttpResponse
from django.template.response import SimpleTemplateResponse
from django.utils.cache import (
cc_delim_re,
get_cache_key,
get_max_age,
has_vary_header,
Expand Down Expand Up @@ -45,6 +46,9 @@ class Status(Enum):


def _patch_header(response: HttpResponse, status: Status) -> None:
"""
Adds our Cache Control status to the response headers.
"""
# Patch cache-control with no-cache if it is not already set.
if status == Status.SKIP and not response.get("Cache-Control", None):
response["Cache-Control"] = CacheControl.NOCACHE.value
Expand All @@ -53,6 +57,31 @@ def _patch_header(response: HttpResponse, status: Status) -> None:
response[wagtailcache_settings.WAGTAIL_CACHE_HEADER] = status.value


def _delete_vary_cookie(response: HttpResponse) -> None:
"""
Deletes the ``Vary: Cookie`` header while keeping other items of the
Vary header in tact. Inspired by ``django.utils.cache.patch_vary_headers``.
"""
if not response.has_header("Vary"):
return
# Parse the value of Vary header.
vary_headers = cc_delim_re.split(response["Vary"])
# Build a lowercase-keyed dict to preserve the original case.
vhdict = {}
for item in vary_headers:
vhdict.update({item.lower(): item})
# Delete "Cookie".
if "cookie" in vhdict:
del vhdict["cookie"]
# Delete the header if it's now empty.
if not vhdict:
del response["Vary"]
return
# Else patch the header.
vary_headers = [vhdict[k] for k in vhdict]
response["Vary"] = ", ".join(vary_headers)


def _chop_querystring(r: WSGIRequest) -> WSGIRequest:
"""
Given a request object, remove any of our ignored querystrings from it.
Expand Down Expand Up @@ -103,15 +132,15 @@ def _chop_response_vary(r: WSGIRequest, s: HttpResponse) -> HttpResponse:
if (
not s.has_header("Set-Cookie")
and s.has_header("Vary")
and s["Vary"].lower() == "cookie"
and has_vary_header(s, "Cookie")
and not (
settings.CSRF_COOKIE_NAME in s.cookies
or settings.CSRF_COOKIE_NAME in r.COOKIES
or settings.SESSION_COOKIE_NAME in s.cookies
or settings.SESSION_COOKIE_NAME in r.COOKIES
)
):
del s["Vary"]
_delete_vary_cookie(s)
return s


Expand Down

0 comments on commit 05df1ad

Please sign in to comment.