From 58699153719e1a49b581ae614b94ba1790317ba7 Mon Sep 17 00:00:00 2001 From: Tom Robinson <tlrobinson@gmail.com> Date: Wed, 31 Oct 2018 14:13:06 -0700 Subject: [PATCH] Far-future cache header for JS/CSS files with cache-busting query strings --- src/metabase/middleware.clj | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/metabase/middleware.clj b/src/metabase/middleware.clj index b8e3e7fc422..00b5117cfbd 100644 --- a/src/metabase/middleware.clj +++ b/src/metabase/middleware.clj @@ -39,6 +39,11 @@ [{:keys [uri]}] (re-matches #"^/embed/.*$" uri)) +(defn- cacheable? + "Can the ring request be permanently cached?" + [{:keys [uri query-string]}] + ;; match requests that are js/css and have a cache-busting query string + (and query-string (re-matches #"^/app/dist/.*\.(js|css)$" uri))) ;;; ------------------------------------------- AUTH & SESSION MANAGEMENT -------------------------------------------- @@ -168,6 +173,11 @@ "Expires" "Tue, 03 Jul 2001 06:00:00 GMT" "Last-Modified" (du/format-date :rfc822)}) + (defn- cache-far-future-headers + "Headers that tell browsers to cache a static resource for a long time." + [] + {"Cache-Control" "public, max-age=31536000"}) + (def ^:private ^:const strict-transport-security-header "Tell browsers to only access this resource over HTTPS for the next year (prevent MTM attacks). (This only applies if the original request was HTTPS; if sent in response to an HTTP request, this is simply ignored)" @@ -216,10 +226,12 @@ (when-let [k (ssl-certificate-public-key)] {"Public-Key-Pins" (format "pin-sha256=\"base64==%s\"; max-age=31536000" k)})) -(defn- security-headers [& {:keys [allow-iframes?] - :or {allow-iframes? false}}] +(defn- security-headers [& {:keys [allow-iframes? allow-cache?] + :or {allow-iframes? false, allow-cache? false}}] (merge - (cache-prevention-headers) + (if allow-cache? + (cache-far-future-headers) + (cache-prevention-headers)) strict-transport-security-header content-security-policy-header #_(public-key-pins-header) @@ -239,7 +251,8 @@ (fn [request] (let [response (handler request)] ;; add security headers to all responses, but allow iframes on public & embed responses - (update response :headers merge (security-headers :allow-iframes? ((some-fn public? embed?) request)))))) + (update response :headers merge (security-headers :allow-iframes? ((some-fn public? embed?) request) + :allow-cache? (cacheable? request)))))) (defn add-content-type "Add an appropriate Content-Type header to response if it doesn't already have one. Most responses should already -- GitLab