mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-05 10:53:28 -05:00
Make URLs for assets cache-proof
https://www.pivotaltracker.com/story/show/113448149 This commit adds a query string to assets URLs which is generated from a hash of the file contents. When asset files are changed they will now be served from a different URL, which means they wont be loaded from browser cache. This is similar to how GOV.UK template adds its version number as a querystring parameter for its assets. This is mostly copied from Digital Marketplace utils: https://github.com/alphagov/digitalmarketplace-utils/pull/102 They have it in a shared codebase, we only have one frontend app so don’t need to do that. Usage in a template: ``` jinja {{ asset_fingerprinter.get_url('stylesheets/application.css') }} ``` Output: ``` static/stylesheets/application.css?418e6f4a6cdf1142e45c072ed3e1c90a ```
This commit is contained in:
46
app/asset_fingerprinter.py
Normal file
46
app/asset_fingerprinter.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import hashlib
|
||||
import codecs
|
||||
|
||||
|
||||
class AssetFingerprinter(object):
|
||||
"""
|
||||
Get a unique hash for an asset file, so that it doesn't stay cached
|
||||
when it changes
|
||||
|
||||
Usage:
|
||||
|
||||
in the application
|
||||
template_data.asset_fingerprinter = AssetFingerprinter()
|
||||
|
||||
where template data is how you pass variables to every template.
|
||||
|
||||
in template.html:
|
||||
{{ asset_fingerprinter.get_url('stylesheets/application.css') }}
|
||||
|
||||
* 'app/static' is assumed to be the root for all asset files
|
||||
"""
|
||||
|
||||
def __init__(self, asset_root='/static/', filesystem_path='app/static/'):
|
||||
self._cache = {}
|
||||
self._asset_root = asset_root
|
||||
self._filesystem_path = filesystem_path
|
||||
|
||||
def get_url(self, asset_path):
|
||||
if asset_path not in self._cache:
|
||||
self._cache[asset_path] = (
|
||||
self._asset_root +
|
||||
asset_path +
|
||||
'?' +
|
||||
self.get_asset_fingerprint(self._filesystem_path + asset_path)
|
||||
)
|
||||
return self._cache[asset_path]
|
||||
|
||||
def get_asset_fingerprint(self, asset_file_path):
|
||||
return hashlib.md5(
|
||||
self.get_asset_file_contents(asset_file_path).encode('utf-8')
|
||||
).hexdigest()
|
||||
|
||||
def get_asset_file_contents(self, asset_file_path):
|
||||
with codecs.open(asset_file_path, encoding='utf-8') as asset_file:
|
||||
contents = asset_file.read()
|
||||
return contents
|
||||
Reference in New Issue
Block a user