summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Cook <JWCook@users.noreply.github.com>2021-10-23 11:37:10 -0500
committerGitHub <noreply@github.com>2021-10-23 11:37:10 -0500
commita70eea1beadcb2d555a7dac77738d0a21900703a (patch)
tree85443bac60fb0a5568cbdd4858b730c9c199d25b
parent37b190a679a28dc25d10749873e0e1f39d447d05 (diff)
parent0b8a8bb1220310cdc6be3d350caf9fbb65b402fb (diff)
downloadrequests-cache-a70eea1beadcb2d555a7dac77738d0a21900703a.tar.gz
Merge pull request #440 from JWCook/immutable
Add support for Cache-Control: immutable
-rw-r--r--HISTORY.md3
-rw-r--r--docs/user_guide/headers.md1
-rw-r--r--requests_cache/cache_control.py11
-rw-r--r--tests/unit/test_cache_control.py2
4 files changed, 12 insertions, 5 deletions
diff --git a/HISTORY.md b/HISTORY.md
index d76f567..b00c478 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -5,7 +5,8 @@
**Expiration & Headers:**
* Use `Cache-Control` **request** headers by default
-* Support immediate expiration + revalidation for `Cache-Control: max-age=0` and `Expires: 0`
+* Add support for `Cache-Control: immutable`
+* Add support for immediate expiration + revalidation with `Cache-Control: max-age=0` and `Expires: 0`
**Backends:**
* Filesystem and SQLite backends: Add better error message if parent path exists but isn't a directory
diff --git a/docs/user_guide/headers.md b/docs/user_guide/headers.md
index a1c7e2f..8373214 100644
--- a/docs/user_guide/headers.md
+++ b/docs/user_guide/headers.md
@@ -56,6 +56,7 @@ The following headers are currently supported:
**Response headers:**
- `Cache-Control: max-age`: Used as the expiration time in seconds
- `Cache-Control: no-store` Skips writing response data to the cache
+- `Cache-Control: immutable`: Caches the response with no expiration
- `Expires`: Used as an absolute expiration time
- `ETag`: Returns expired cache data if the remote content has not changed (`304 Not Modified` response)
- `Last-Modified`: Returns expired cache data if the remote content has not changed (`304 Not Modified` response)
diff --git a/requests_cache/cache_control.py b/requests_cache/cache_control.py
index 604820f..5b238d8 100644
--- a/requests_cache/cache_control.py
+++ b/requests_cache/cache_control.py
@@ -28,7 +28,7 @@ __all__ = ['DO_NOT_CACHE', 'CacheActions']
# May be set by either headers or expire_after param to disable caching
DO_NOT_CACHE = 0
# Supported Cache-Control directives
-CACHE_DIRECTIVES = ['max-age', 'no-cache', 'no-store']
+CACHE_DIRECTIVES = ['immutable', 'max-age', 'no-cache', 'no-store']
CacheDirective = Tuple[str, Union[None, int, bool]]
ExpirationTime = Union[None, int, float, str, datetime, timedelta]
@@ -136,9 +136,12 @@ class CacheActions:
logger.debug(f'Cache directives from response headers: {directives}')
# Check headers for expiration, validators, and other cache directives
- self.expire_after = coalesce(
- directives.get('max-age'), directives.get('expires'), self.expire_after
- )
+ if directives.get('immutable'):
+ self.expire_after = -1
+ else:
+ self.expire_after = coalesce(
+ directives.get('max-age'), directives.get('expires'), self.expire_after
+ )
has_validator = response.headers.get('ETag') or response.headers.get('Last-Modified')
no_store = 'no-store' in directives or 'no-store' in self.request_directives
diff --git a/tests/unit/test_cache_control.py b/tests/unit/test_cache_control.py
index cb8ea96..54182e3 100644
--- a/tests/unit/test_cache_control.py
+++ b/tests/unit/test_cache_control.py
@@ -206,6 +206,8 @@ def test_update_from_cached_response__ignored():
({'Cache-Control': 'public, max-age=60'}, 60),
({'Cache-Control': 'max-age=0'}, DO_NOT_CACHE),
({'Cache-Control': 'no-store'}, DO_NOT_CACHE),
+ ({'Cache-Control': 'immutable'}, -1),
+ ({'Cache-Control': 'immutable, max-age=60'}, -1), # Immutable should take precedence
({'Expires': HTTPDATE_STR}, HTTPDATE_STR),
({'Expires': HTTPDATE_STR, 'Cache-Control': 'max-age=60'}, 60),
],