Skip to content

Commit

Permalink
Merge pull request #9 from twiebe/release-0.3
Browse files Browse the repository at this point in the history
Prepare release 0.3.0
  • Loading branch information
twiebe authored Jun 3, 2022
2 parents 5bf5283 + a52c959 commit 01eccbd
Show file tree
Hide file tree
Showing 9 changed files with 409 additions and 301 deletions.
64 changes: 49 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
# Flask-CacheControl

## Description:
## Description

A light-weight library to conveniently set Cache-Control
A light-weight library to conveniently set `Cache-Control`
headers on the response. Decorate view functions with
cache_for, cache, or dont_cache decorators. Makes use of
Flask response.cache_control.
`cache_for`, `cache`, or `dont_cache` decorators. Makes use of
Flask `response.cache_control`.

This extension does not provide any caching of its own. Its sole
purpose is to set Cache-Control and related HTTP headers on the
purpose is to set `Cache-Control` and related HTTP headers on the
response, so that clients, intermediary proxies or reverse proxies
in your jurisdiction which evaluate Cache-Control headers, such as
in your jurisdiction which evaluate `Cache-Control` headers, such as
Varnish Cache, do the caching for you.

## Example:
By default, `Cache-Control` headers are only appended in case of a
successful response (status code 2xx). This behaviour can be controlled
with the `only_if` argument to `cache_for` and `cache` decorators. Included
options are `Always`, `ResponseIsSuccessful`, `ResponseIsSuccessfulOrRedirect`. Custom behaviour can be implemented by subclassing `OnlyIfEvaluatorBase`.

If the `vary` keyword argument is given to `cache_for` or `cache`
decorators, the `Vary` HTTP header is returned with the response.
`Vary` headers are appended independent of response status code.

## Example
```python
from flask import Flask, render_template
from flask_cachecontrol import (
FlaskCacheControl,
cache,
cache_for,
dont_cache)
flask_cache_control = FlaskCacheControl()
flask_cache_control.init_app(app)
dont_cache,
Always,
ResponseIsSuccessfulOrRedirect)


app = Flask(__name__)


@app.route('/')
@cache_for(hours=3)
def index_view():
return render_template('index_template')

@app.route('/users')
@cache_for(minutes=5, only_if=ResponseIsSuccessfulOrRedirect)
def users_view():
return render_template('user_template')

@app.route('/stats')
@cache(max_age=3600, public=True)
@cache(max_age=3600, public=True, only_if=Always, vary=['User-Agent', 'Referer'])
def stats_view():
return render_template('stats_template')

Expand All @@ -39,8 +57,24 @@ def dashboard_view():
return render_template('dashboard_template')
```

## Breaking Changes:
## Changelog
### 0.3.0
- Add `only_if` evaluator for _successful or redirect (2xx, 3xx)_ responses (#7)
- Support **Vary**-headers (#6)
- Improve instantiation of callbacks and registry provider
- **BREAKING**: Simplify instantiation and hooking into flask response handling (#8)
- No more need to instantiate `FlaskCacheControl` for Flask app.
- **BREAKING**: Drop support for `only_if=None`
- Use more explicit `only_if=Always` instead
- **BREAKING**: Restructure modules
- Direct imports from modules inside the package need to be adapted.
- Improve test structuring
- Fix flask instantiation and import in example

### v0.2.1
- Fix import statement in example

### v0.2.0
- By default, cache control headers are only applied to successful requests. (status code `2xx`) This behaviour can be customized by providing `only_if=` as a kw to all caching decorators.
- Requires python 3.3 or higher
- Add tests
- **BREAKING**: By default, cache control headers are only applied to successful requests. (status code `2xx`) This behaviour can be customized by providing `only_if=` as a kw to all caching decorators.
- **BREAKING**: Requires python 3.3 or higher
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
url='https://github.com/twiebe/Flask-CacheControl',
license='BSD',
author='Thomas Wiebe',
author_email='[email protected]',
author_email='thomas+[email protected]',
description='Set Cache-Control headers on the Flask response',
long_description=open('README.md', 'r').read(),
long_description_content_type="text/markdown",
Expand Down
5 changes: 3 additions & 2 deletions src/flask_cachecontrol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
:license: BSD, see LICENSE for more details.
"""

from .cache import cache, cache_for, dont_cache, FlaskCacheControl, Always, ResponseIsSuccessful
from .decorate import cache, cache_for, dont_cache
from .evaluator import Always, ResponseIsSuccessful, ResponseIsSuccessfulOrRedirect
from .error import FlaskCacheControlError, CacheControlAttributeInvalidError

__version__ = '0.2.1'
__version__ = '0.3.0'
75 changes: 0 additions & 75 deletions src/flask_cachecontrol/after_this_request.py

This file was deleted.

141 changes: 0 additions & 141 deletions src/flask_cachecontrol/cache.py

This file was deleted.

27 changes: 23 additions & 4 deletions src/flask_cachecontrol/callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,27 @@
:license: BSD, see LICENSE for more details.
"""

from abc import ABCMeta, abstractmethod
from datetime import datetime

from .after_this_request import CallbackBase
from .error import CacheControlAttributeInvalidError


class CallbackBase(metaclass=ABCMeta):
def __call__(self, response):
self._process_response(response)
return response

@abstractmethod
def _process_response(self, response):
pass


class SetCacheControlHeadersFromTimedeltaCallback(CallbackBase):
def __init__(self, timedelta):
self._timedelta = timedelta

def __call__(self, response):
def _process_response(self, response):
response.expires = datetime.utcnow() + self._timedelta
response.cache_control.max_age = int(self._timedelta.total_seconds())

Expand All @@ -26,7 +36,7 @@ class SetCacheControlHeadersCallback(CallbackBase):
def __init__(self, **cache_control_kw):
self._cache_control_kw = cache_control_kw

def __call__(self, response):
def _process_response(self, response):
cache_control = response.cache_control
for attr_name, value in self._cache_control_kw.items():
if not hasattr(cache_control, attr_name):
Expand All @@ -35,9 +45,18 @@ def __call__(self, response):


class SetCacheControlHeadersForNoCachingCallback(CallbackBase):
def __call__(self, response):
def _process_response(self, response):
response.cache_control.max_age = 0
response.cache_control.no_cache = True
response.cache_control.no_store = True
response.cache_control.must_revalidate = True
response.cache_control.proxy_revalidate = True


class SetVaryHeaderCallback(CallbackBase):
def __init__(self, vary):
# generate string version once for object lifetime
self._vary_header = ','.join(vary) if vary is not None else None

def _process_response(self, response):
response.vary = self._vary_header
Loading

0 comments on commit 01eccbd

Please sign in to comment.