diff --git a/endpoints/common.py b/endpoints/common.py
index 090708e39..3534ee072 100644
--- a/endpoints/common.py
+++ b/endpoints/common.py
@@ -3,6 +3,7 @@ import urlparse
import json
import string
import datetime
+import os
# Register the various exceptions via decorators.
import endpoints.decorated
@@ -32,6 +33,23 @@ profile = logging.getLogger('application.profiler')
route_data = None
+CACHE_BUSTERS_JSON = 'static/dist/cachebusters.json'
+CACHE_BUSTERS = None
+
+def get_cache_busters():
+ """ Retrieves the cache busters hashes. """
+ global CACHE_BUSTERS
+ if CACHE_BUSTERS is not None:
+ return CACHE_BUSTERS
+
+ if not os.path.exists(CACHE_BUSTERS_JSON):
+ return {}
+
+ with open(CACHE_BUSTERS_JSON, 'r') as f:
+ CACHE_BUSTERS = json.loads(f.read())
+ return CACHE_BUSTERS
+
+
class RepoPathConverter(BaseConverter):
regex = '[\.a-zA-Z0-9_\-]+/[\.a-zA-Z0-9_\-]+'
weight = 200
@@ -113,17 +131,15 @@ def list_files(path, extension):
filepath = 'static/' + path
return [join_path(dp, f) for dp, dn, files in os.walk(filepath) for f in files if matches(f)]
-SAVED_CACHE_STRING = random_string()
-
def render_page_template(name, **kwargs):
- if app.config.get('DEBUGGING', False):
+ debugging = app.config.get('DEBUGGING', False)
+ if debugging:
# If DEBUGGING is enabled, then we load the full set of individual JS and CSS files
# from the file system.
library_styles = list_files('lib', 'css')
main_styles = list_files('css', 'css')
library_scripts = list_files('lib', 'js')
main_scripts = list_files('js', 'js')
- cache_buster = 'debugging'
file_lists = [library_styles, main_styles, library_scripts, main_scripts]
for file_list in file_lists:
@@ -133,7 +149,6 @@ def render_page_template(name, **kwargs):
main_styles = ['dist/quay-frontend.css']
library_scripts = []
main_scripts = ['dist/quay-frontend.min.js']
- cache_buster = SAVED_CACHE_STRING
use_cdn = app.config.get('USE_CDN', True)
if request.args.get('use_cdn') is not None:
@@ -142,6 +157,12 @@ def render_page_template(name, **kwargs):
external_styles = get_external_css(local=not use_cdn)
external_scripts = get_external_javascript(local=not use_cdn)
+ def add_cachebusters(filenames):
+ cachebusters = get_cache_busters()
+ for filename in filenames:
+ cache_buster = cachebusters.get(filename, random_string()) if not debugging else 'debugging'
+ yield (filename, cache_buster)
+
def get_oauth_config():
oauth_config = {}
for oauth_app in oauth_apps:
@@ -153,13 +174,14 @@ def render_page_template(name, **kwargs):
if len(app.config.get('CONTACT_INFO', [])) == 1:
contact_href = app.config['CONTACT_INFO'][0]
- resp = make_response(render_template(name, route_data=json.dumps(get_route_data()),
+ resp = make_response(render_template(name,
+ route_data=json.dumps(get_route_data()),
external_styles=external_styles,
external_scripts=external_scripts,
- main_styles=main_styles,
- library_styles=library_styles,
- main_scripts=main_scripts,
- library_scripts=library_scripts,
+ main_styles=add_cachebusters(main_styles),
+ library_styles=add_cachebusters(library_styles),
+ main_scripts=add_cachebusters(main_scripts),
+ library_scripts=add_cachebusters(library_scripts),
feature_set=json.dumps(features.get_features()),
config_set=json.dumps(getFrontendVisibleConfig(app.config)),
oauth_set=json.dumps(get_oauth_config()),
@@ -169,7 +191,6 @@ def render_page_template(name, **kwargs):
sentry_public_dsn=app.config.get('SENTRY_PUBLIC_DSN', ''),
is_debug=str(app.config.get('DEBUGGING', False)).lower(),
show_chat=features.OLARK_CHAT,
- cache_buster=cache_buster,
has_billing=features.BILLING,
contact_href=contact_href,
hostname=app.config['SERVER_HOSTNAME'],
diff --git a/grunt/Gruntfile.js b/grunt/Gruntfile.js
index 5dd381e8d..e9cb14818 100644
--- a/grunt/Gruntfile.js
+++ b/grunt/Gruntfile.js
@@ -68,6 +68,18 @@ module.exports = function(grunt) {
src: ['../static/partials/*.html', '../static/directives/*.html'],
dest: '../static/dist/template-cache.js'
}
+ },
+
+ cachebuster: {
+ build: {
+ options: {
+ format: 'json',
+ basedir: '../static/'
+ },
+ src: [ '../static/dist/template-cache.js', '../static/dist/<%= pkg.name %>.min.js',
+ '../static/dist/<%= pkg.name %>.css' ],
+ dest: '../static/dist/cachebusters.json'
+ }
}
});
@@ -75,7 +87,8 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-angular-templates');
+ grunt.loadNpmTasks('grunt-cachebuster');
// Default task(s).
- grunt.registerTask('default', ['ngtemplates', 'concat', 'cssmin', 'uglify']);
+ grunt.registerTask('default', ['ngtemplates', 'concat', 'cssmin', 'uglify', 'cachebuster']);
};
diff --git a/grunt/package.json b/grunt/package.json
index e4d9836a3..0ea53569b 100644
--- a/grunt/package.json
+++ b/grunt/package.json
@@ -6,6 +6,7 @@
"grunt-contrib-concat": "~0.4.0",
"grunt-contrib-cssmin": "~0.9.0",
"grunt-angular-templates": "~0.5.4",
- "grunt-contrib-uglify": "~0.4.0"
+ "grunt-contrib-uglify": "~0.4.0",
+ "grunt-cachebuster": "~0.1.5"
}
}
diff --git a/templates/base.html b/templates/base.html
index 9c4b0fed0..122a69614 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -28,11 +28,11 @@
- {% for style_path in main_styles %}
+ {% for style_path, cache_buster in main_styles %}
{% endfor %}
- {% for style_path in library_styles %}
+ {% for style_path, cache_buster in library_styles %}
{% endfor %}
@@ -53,7 +53,7 @@
{% endfor %}
- {% for script_path in library_scripts %}
+ {% for script_path, cache_buster in library_scripts %}
{% endfor %}
@@ -61,7 +61,7 @@
{% endblock %}
- {% for script_path in main_scripts %}
+ {% for script_path, cache_buster in main_scripts %}
{% endfor %}