summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/api/interfaces.rst2
-rw-r--r--docs/api/static.rst7
-rw-r--r--docs/narr/assets.rst72
-rw-r--r--pyramid/config/views.py15
-rw-r--r--pyramid/interfaces.py14
-rw-r--r--pyramid/static.py41
6 files changed, 129 insertions, 22 deletions
diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst
index d8d935afd..a62976d8a 100644
--- a/docs/api/interfaces.rst
+++ b/docs/api/interfaces.rst
@@ -86,3 +86,5 @@ Other Interfaces
.. autointerface:: IResourceURL
:members:
+ .. autointerface:: ICacheBuster
+ :members:
diff --git a/docs/api/static.rst b/docs/api/static.rst
index c28473584..8ea2fff75 100644
--- a/docs/api/static.rst
+++ b/docs/api/static.rst
@@ -9,3 +9,10 @@
:members:
:inherited-members:
+ .. autoclass:: PathSegmentCacheBuster
+ :members:
+
+ .. autoclass:: QueryStringCacheBuster
+ :members:
+
+ .. autofunction:: Md5AssetTokenGenerator
diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst
index a2976de22..97d473761 100644
--- a/docs/narr/assets.rst
+++ b/docs/narr/assets.rst
@@ -315,7 +315,7 @@ requests a copy, regardless of any caching policy set for the resource's old
URL.
:app:`Pyramid` can be configured to produce cache busting URLs for static
-assets by passing the optional argument, `cache_bust` to
+assets by passing the optional argument, ``cachebuster`` to
:meth:`~pyramid.config.Configurator.add_static_view`:
.. code-block:: python
@@ -323,27 +323,22 @@ assets by passing the optional argument, `cache_bust` to
# config is an instance of pyramid.config.Configurator
config.add_static_view(name='static', path='mypackage:folder/static',
- cache_bust='md5')
+ cachebuster=True)
-Supplying the `cache_bust` argument instructs :app:`Pyramid` to add a query
-string to URLs generated for this static view which includes the md5 checksum
-of the static file being served:
+Setting the ``cachebuster`` argument instructs :app:`Pyramid` to use a cache
+busting scheme which adds the md5 checksum for a static asset as a path segment
+in the asset's URL:
.. code-block:: python
:linenos:
js_url = request.static_url('mypackage:folder/static/js/myapp.js')
- # Returns: 'http://www.example.com/static/js/myapp.js?md5=c9658b3c0a314a1ca21e5988e662a09e`
+ # Returns: 'http://www.example.com/static/c9658b3c0a314a1ca21e5988e662a09e/js/myapp.js`
When the asset changes, so will its md5 checksum, and therefore so will its
-URL. Supplying the `cache_bust` argument also causes the static view to set
+URL. Supplying the ``cachebuster`` argument also causes the static view to set
headers instructing clients to cache the asset for ten years, unless the
-`max_cache_age` argument is also passed, in which case that value is used.
-
-.. note::
-
- `md5` is currently the only possible value for the `cache_bust` argument to
- :meth:`~pyramid.config.Configurator.add_static_view`.
+``max_cache_age`` argument is also passed, in which case that value is used.
.. note::
@@ -351,6 +346,57 @@ headers instructing clients to cache the asset for ten years, unless the
restarting your application, you may still generate URLs with a stale md5
checksum.
+Customizing the Cache Buster
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Revisiting from the previous section:
+
+.. code-block:: python
+ :linenos:
+
+ # config is an instance of pyramid.config.Configurator
+ config.add_static_view(name='static', path='mypackage:folder/static',
+ cachebuster=True)
+
+Setting ``cachebuster`` to ``True`` instructs :app:`Pyramid` to use a default
+cache busting implementation that should work for many situations. The
+``cachebuster`` may be set to any object that implements the interface,
+:class:`~pyramid.interfaces.ICacheBuster`. The above configuration is exactly
+equivalent to:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.static import (
+ Md5AssetTokenGenerator,
+ PathSegmentCacheBuster)
+
+ # config is an instance of pyramid.config.Configurator
+ cachebuster = PathSegmentCacheBuster(Md5AssetTokenGenerator())
+ config.add_static_view(name='static', path='mypackage:folder/static',
+ cachebuster=cachebuster)
+
+:app:`Pyramid` includes two ready to use cache buster implementations:
+:class:`~pyramid.static.PathSegmentCacheBuster`, which inserts an asset token
+in the path portion of the asset's URL, and
+:class:`~pyramid.static.QueryStringCacheBuster`, which adds an asset token to
+the query string of the asset's URL. Both of these classes have constructors
+which accept a token generator function as an argument, allowing for the way a
+token is generated to be decoupled from the way it is inserted into a URL.
+:app:`Pyramid` provides a single asset token generator,
+:meth:`~pyramid.static.Md5AssetTokenGenerator`.
+
+In order to implement your own cache buster, see the
+:class:`~pyramid.interfaces.ICacheBuster` interface and the existing
+implementations in the :mod:`~pyramid.static` module.
+
+.. note::
+
+ Many HTTP caching proxy implementations will fail to cache any URL which
+ has a query string. For this reason, you should probably prefer
+ :class:`~pyramid.static.PathSegementCacheBuster` to
+ :class:`~pyramid.static.QueryStringCacheBuster`.
+
.. index::
single: static assets view
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 00c5622e7..d74ecfadb 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -1788,11 +1788,16 @@ class ViewsConfiguratorMixin(object):
particular Expires or Cache-Control headers are set in the response,
unless ``cache_bust`` is specified.
- The ``cache_bust`` keyword argument may be set to ``"md5"`` to cause
- :meth:`~pyramid.request.Request.static_url` to generate URLs with an
- additional query string which includes the md5 checksum for the static
- asset. This argument modifies the default for ``cache_max_age``,
- making it ten years. ``cache_max_age`` may still be explicitly
+ The ``cachebuster`` keyword argument may be set to cause
+ :meth:`~pyramid.request.Request.static_url` to use cache busting when
+ generating URLs. See :ref:`cache_busting` for general information
+ about cache busting. The value of the ``cachebuster`` argument may be
+ ``True``, in which case a default cache busting implementation is used.
+ The value of the ``cachebuster`` argument may also be an object which
+ implements :class:`~pyramid.interfaces.ICacheBuster`. See the
+ :mod:`~pyramid.static` module for some implementations. If the
+ ``cachebuster`` argument is provided, the default for ``cache_max_age``
+ is modified to be ten years. ``cache_max_age`` may still be explicitly
provided to override this default.
The ``permission`` keyword argument is used to specify the
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index 822d1624c..f3d7b1798 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -1168,6 +1168,12 @@ class ICacheBuster(Interface):
"""
A container for functions which implement a cache busting policy for
serving static assets.
+
+ The implementations provided by :app:`Pyramid` use standard instance
+ methods for ``pregenerate`` and ``match``, while accepting an
+ implementation of ``token`` as an argument to their constructor. This
+ pattern allows for the decoupling of how a token is generated and how it is
+ inserted into a URL. For examples see the :mod:`~pyramid.static` module.
"""
def token(pathspec):
"""
@@ -1197,7 +1203,7 @@ class ICacheBuster(Interface):
A function which modifies a subpath and/or keyword arguments from which
a static asset URL will be computed during URL generation. The
``token`` argument is a token string computed by an instance of
- :method:`~pyramid.interfaces.ICacheBuster.token` for a particular
+ :meth:`~pyramid.interfaces.ICacheBuster.token` for a particular
asset. The ``subpath`` argument is a tuple of path elements that
represent the portion of the asset URL which is used to find the asset.
The ``kw`` argument is a dict of keywords that are to be passed
@@ -1218,9 +1224,9 @@ class ICacheBuster(Interface):
def match(subpath):
"""
- A function which performs the logical inverse of an
- :method:`~pyramid.interfaces.ICacheBuster.pregenerate`, by taking a
- subpath from a cache busted URL and removing the cachebust token, so
+ A function which performs the logical inverse of
+ :meth:`~pyramid.interfaces.ICacheBuster.pregenerate` by taking a
+ subpath from a cache busted URL and removing the cache bust token, so
that :app:`Pyramid` can find the underlying asset.
``subpath`` is the subpath portion of the URL for an incoming request
diff --git a/pyramid/static.py b/pyramid/static.py
index 09743ac15..ab9d47aa5 100644
--- a/pyramid/static.py
+++ b/pyramid/static.py
@@ -166,6 +166,12 @@ def _generate_md5(spec):
return md5.hexdigest()
def Md5AssetTokenGenerator():
+ """
+ A factory method which returns a function that implements
+ :meth:`~pyramid.interfaces.ICacheBuster.token`. The function computes and
+ returns md5 checksums for static assets, caching them in memory for speedy
+ retrieval on subsequent calls.
+ """
token_cache = {}
def generate_token(pathspec):
@@ -189,7 +195,23 @@ def Md5AssetTokenGenerator():
return generate_token
class PathSegmentCacheBuster(object):
+ """
+ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which
+ inserts a token for cache busting in the path portion of an asset URL.
+
+ The ``token`` argument should be an implementation of
+ :meth:`~pyramid.interfaces.ICacheBuster.token`. For example, to use
+ this cache buster with an md5 token generator:
+ .. code-block:: python
+ :linenos:
+
+ from pyramid.static import (
+ Md5AssetTokenGenerator,
+ PathSegmentCacheBuster)
+
+ cachebuster = PathSegmentCacheBuster(Md5AssetTokenGenerator())
+ """
def __init__(self, token):
self.token = token
@@ -200,7 +222,26 @@ class PathSegmentCacheBuster(object):
return subpath[1:]
class QueryStringCacheBuster(object):
+ """
+ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which
+ adds a token for cache busting in the query string of an asset URL.
+
+ The ``token`` argument should be an implementation of
+ :meth:`~pyramid.interfaces.ICacheBuster.token`. For example, to use
+ this cache buster with an md5 token generator:
+
+ .. code-block:: python
+ :linenos:
+ from pyramid.static import (
+ Md5AssetTokenGenerator,
+ PathSegmentCacheBuster)
+
+ cachebuster = QueryStringCacheBuster(Md5AssetTokenGenerator())
+
+ The optional ``param`` argument determines the name of the parameter added
+ to the query string and defaults to ``'x'``.
+ """
def __init__(self, token, param='x'):
self.param = param
self.token = token