diff --git a/cps/cache_buster.py b/cps/cache_buster.py new file mode 100644 index 00000000..d6b7260d --- /dev/null +++ b/cps/cache_buster.py @@ -0,0 +1,57 @@ +# Inspired by https://github.com/ChrisTM/Flask-CacheBust +# Uses query strings so CSS font files are found without having to resort to absolute URLs + +import hashlib +import os + + +def init_cache_busting(app): + """ + Configure `app` to so that `url_for` adds a unique query string to URLs generated + for the `'static'` endpoint. + + This allows setting long cache expiration values on static resources + because whenever the resource changes, so does its URL. + """ + + static_folder = app.static_folder # the rooted path to the static file folder + + hash_table = {} # map of file hashes + + app.logger.debug('Computing cache-busting values...') + # compute file hashes + for dirpath, dirnames, filenames in os.walk(static_folder): + for filename in filenames: + # compute version component + rooted_filename = os.path.join(dirpath, filename) + with open(rooted_filename, 'r') as f: + version = hashlib.md5(f.read()).hexdigest()[:7] + + # save version to tables + file_path = rooted_filename.replace(static_folder + "/", "") + hash_table[file_path] = version + app.logger.debug('Finished computing cache-busting values') + + def bust_filename(filename): + return hash_table.get(filename, "") + + def unbust_filename(filename): + return filename.split("?", 1)[0] + + @app.url_defaults + def reverse_to_cache_busted_url(endpoint, values): + """ + Make `url_for` produce busted filenames when using the 'static' endpoint. + """ + if endpoint == 'static': + values["q"] = bust_filename(values['filename']) + + def debusting_static_view(filename): + """ + Serve a request for a static file having a busted name. + """ + return original_static_view(filename=unbust_filename(filename)) + + # Replace the default static file view with our debusting view. + original_static_view = app.view_functions['static'] + app.view_functions['static'] = debusting_static_view diff --git a/cps/web.py b/cps/web.py index f51cbc5c..9088551c 100755 --- a/cps/web.py +++ b/cps/web.py @@ -21,6 +21,7 @@ from flask import (Flask, render_template, request, Response, redirect, url_for, send_from_directory, make_response, g, flash, abort, Markup, stream_with_context) from flask import __version__ as flaskVersion +import cache_buster import ub from ub import config import helper @@ -200,6 +201,7 @@ mimetypes.add_type('image/vnd.djvu', '.djvu') app = (Flask(__name__)) app.wsgi_app = ReverseProxied(app.wsgi_app) +cache_buster.init_cache_busting(app) gevent_server = None