From 2b7e05b10787f283d53ddb78edc2dec0618502da Mon Sep 17 00:00:00 2001 From: Cal Paterson Date: Mon, 9 Sep 2024 15:25:56 +0300 Subject: [PATCH 1/2] Add support for RFC5861 Cache-Control headers stale-while-revalidate and stale-if-error --- src/werkzeug/datastructures/cache_control.py | 2 ++ tests/test_datastructures.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/werkzeug/datastructures/cache_control.py b/src/werkzeug/datastructures/cache_control.py index 6ff4eceeb..20a5179c9 100644 --- a/src/werkzeug/datastructures/cache_control.py +++ b/src/werkzeug/datastructures/cache_control.py @@ -186,6 +186,8 @@ class ResponseCacheControl(_CacheControl): s_maxage = cache_control_property("s-maxage", None, int) immutable = cache_control_property("immutable", None, bool) must_understand = cache_control_property("must-understand", None, bool) + stale_while_revalidate = cache_control_property("stale-while-revalidate", None, int) + stale_if_error = cache_control_property("stale-if-error", None, int) # circular dependencies diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index 830dfefd5..09e748fdd 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -973,6 +973,19 @@ def test_must_understand(self): cc = ds.ResponseCacheControl() assert cc.must_understand is False + def test_stale_while_revalidate(self): + cc = ds.ResponseCacheControl([("stale-while-revalidate", "1")]) + assert cc.stale_while_revalidate == 1 + cc = ds.ResponseCacheControl() + assert cc.stale_while_revalidate is None + + def test_stale_if_error(self): + cc = ds.ResponseCacheControl([("stale-if-error", "1")]) + assert cc.stale_if_error == 1 + cc = ds.ResponseCacheControl() + assert cc.stale_while_revalidate is None + + class TestContentSecurityPolicy: def test_construct(self): From 491d99fc2060d34db76303fda311bc242ebf2a5f Mon Sep 17 00:00:00 2001 From: Cal Paterson Date: Mon, 9 Sep 2024 15:28:34 +0300 Subject: [PATCH 2/2] Add type annotations for RFC5861 additions --- src/werkzeug/datastructures/cache_control.pyi | 12 ++++++++++++ tests/test_datastructures.py | 1 - 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/werkzeug/datastructures/cache_control.pyi b/src/werkzeug/datastructures/cache_control.pyi index 4c9f4df37..93c595db8 100644 --- a/src/werkzeug/datastructures/cache_control.pyi +++ b/src/werkzeug/datastructures/cache_control.pyi @@ -116,3 +116,15 @@ class ResponseCacheControl(_CacheControl): def must_understand(self, value: bool | None) -> None: ... @must_understand.deleter def must_understand(self) -> None: ... + @property + def stale_while_revalidate(self) -> int | None: ... + @stale_while_revalidate.setter + def stale_while_revalidate(self, value: int | None) -> None: ... + @stale_while_revalidate.deleter + def stale_while_revalidate(self) -> None: ... + @property + def stale_if_error(self) -> int | None: ... + @stale_if_error.setter + def stale_if_error(self, value: int | None) -> None: ... + @stale_if_error.deleter + def stale_if_error(self) -> None: ... diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index 09e748fdd..a681c022b 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -986,7 +986,6 @@ def test_stale_if_error(self): assert cc.stale_while_revalidate is None - class TestContentSecurityPolicy: def test_construct(self): csp = ds.ContentSecurityPolicy([("font-src", "'self'"), ("media-src", "*")])