From ac66eb07e94efa95aa3a24947b9dd922d50d9cda Mon Sep 17 00:00:00 2001 From: TLSM Date: Sat, 24 Sep 2022 02:40:26 -0400 Subject: [PATCH] Implement hash-based cachebusting module. Adds the files.helpers.assetcache module, which runs on worker startup to compute CRC digests of files in given asset directories and provides a Jinja filter to create cachebusted URLs based on those hashes. This alleviates the need to increment cachebusting counters in query strings entirely for files it is applied to. --- files/helpers/assetcache.py | 32 ++++++++++++++++++++++++++++++++ files/helpers/jinja2.py | 6 ++++++ 2 files changed, 38 insertions(+) create mode 100644 files/helpers/assetcache.py diff --git a/files/helpers/assetcache.py b/files/helpers/assetcache.py new file mode 100644 index 0000000000..f3bf2408a7 --- /dev/null +++ b/files/helpers/assetcache.py @@ -0,0 +1,32 @@ +import os +import zlib +from collections import defaultdict + +ASSET_DIR = 'files/assets' +ASSET_SUBDIRS = ['/css', '/js'] +ASSET_URL = '/assets/' +ASSET_CACHE = defaultdict(lambda: None) + +def assetcache_build(asset_dir, subdirs): + for subdir in subdirs: + for root, dirs, files in os.walk(asset_dir + subdir): + for fname in files: + fpath = root + '/' + fname + relpath = fpath[len(asset_dir) + 1:].replace('\\', '/') + with open(fpath, 'rb') as f: + fhash = zlib.crc32(f.read()) + ASSET_CACHE[relpath] = '%x' % fhash + +def assetcache_hash(asset_path): + return ASSET_CACHE[asset_path] + +def assetcache_path(asset_path): + cachehash = assetcache_hash(asset_path) + + url = ASSET_URL + asset_path + if cachehash: + url += '?v=' + cachehash + + return url + +assetcache_build(ASSET_DIR, ASSET_SUBDIRS) diff --git a/files/helpers/jinja2.py b/files/helpers/jinja2.py index e6d70e0bf9..8c7b147925 100644 --- a/files/helpers/jinja2.py +++ b/files/helpers/jinja2.py @@ -3,6 +3,7 @@ from .get import * from os import listdir, environ from .const import * import time +from files.helpers.assetcache import assetcache_path @app.template_filter("post_embed") def post_embed(id, v): @@ -16,6 +17,11 @@ def post_embed(id, v): return '' +@app.template_filter("asset") +def template_asset(asset_path): + return assetcache_path(asset_path) + + @app.template_filter("timestamp") def timestamp(timestamp):