Permalink
Browse files

Automatically version static files.

Also mark them as permanently cacheable. Closes #102.
  • Loading branch information...
1 parent 31ef432 commit 2eb08aeec921551104131ab96e397dbbe3720738 @amalloy amalloy committed Sep 14, 2011
Showing with 52 additions and 17 deletions.
  1. +3 −2 src/foreclojure/core.clj
  2. +12 −0 src/foreclojure/git.clj
  3. +9 −0 src/foreclojure/ring.clj
  4. +25 −7 src/foreclojure/utils.clj
  5. +3 −8 src/foreclojure/version.clj
View
@@ -8,7 +8,7 @@
[foreclojure.login :only [login-routes]]
[foreclojure.register :only [register-routes]]
[foreclojure.golf :only [golf-routes]]
- [foreclojure.ring :only [resources wrap-strip-trailing-slash wrap-url-as-file]]
+ [foreclojure.ring :only [resources wrap-strip-trailing-slash wrap-url-as-file wrap-versioned-expiry]]
[foreclojure.users :only [users-routes]]
[foreclojure.config :only [config]]
[foreclojure.social :only [social-routes]]
@@ -37,7 +37,8 @@
golf-routes
(-> (resources "/*")
(wrap-url-as-file)
- (wrap-file-info))
+ (wrap-file-info)
+ (wrap-versioned-expiry))
(route/not-found "Page not found"))
(def app (-> #'main-routes
View
@@ -0,0 +1,12 @@
+(ns foreclojure.git
+ (:require [clojure.string :as s])
+ (:use [clojure.java.shell :only [sh]]))
+
+(letfn [(cmd [& args]
+ (not-empty (s/trim (:out (apply sh args)))))]
+
+ ;; fetch these at load time rather than on demand, so that it's accurate even
+ ;; if someone checks out a different revision to poke at without restarting
+ ;; the server (eg to diagnose bugs in a release)
+ (def sha (cmd "git" "rev-parse" "--verify" "HEAD"))
+ (def tag (cmd "git" "describe" "--abbrev=0" "master")))
View
@@ -3,6 +3,7 @@
[clojure.string :as s])
(:import [java.net URL])
(:use [compojure.core :only [GET]]
+ [foreclojure.utils :only [strip-version-number]]
[ring.util.response :only [response]]))
;; copied from compojure.route, modified to use File instead of Stream
@@ -27,3 +28,11 @@
(defn wrap-strip-trailing-slash [handler]
(fn [request]
(handler (update-in request [:uri] s/replace #"(?<=.)/$" ""))))
+
+(defn wrap-versioned-expiry [handler]
+ (fn [request]
+ (-> request
+ (update-in [:uri] strip-version-number)
+ (handler)
+ (assoc-in [:headers "Cache-control"]
+ "public, max-age=31536000"))))
View
@@ -1,11 +1,14 @@
(ns foreclojure.utils
(:require [sandbar.stateful-session :as session]
[ring.util.response :as response]
- [clojure.walk :as walk])
+ [clojure.walk :as walk]
+ [clojure.string :as string]
+ [foreclojure.git :as git]
+ [hiccup.page-helpers :as hiccup])
(:import [java.net URLEncoder]
[org.apache.commons.mail HtmlEmail])
(:use [hiccup.core :only [html]]
- [hiccup.page-helpers :only [doctype include-css javascript-tag link-to include-js]]
+ [hiccup.page-helpers :only [doctype javascript-tag link-to]]
[hiccup.form-helpers :only [label]]
[useful.fn :only [to-fix]]
[somnium.congomongo :only [fetch-one]]
@@ -145,6 +148,21 @@
(defn rendering-info [attributes]
(into defaults attributes)))
+(let [version-suffix (str "__" git/tag)]
+ (defn add-version-number [file]
+ (let [[_ path ext] (re-find #"(.*)\.(.*)$" file)]
+ (str path version-suffix "." ext)))
+
+ (defn strip-version-number [file]
+ (string/replace file version-suffix "")))
+
+(letfn [(wrap-versioning [f]
+ (fn [& files]
+ (for [file files]
+ (f (add-version-number file)))))]
+ (def js (wrap-versioning hiccup/include-js))
+ (def css (wrap-versioning hiccup/include-css)))
+
(defn html-doc [body]
(let [attrs (rendering-info (page-attributes body))
user (session/session-get :user)]
@@ -155,11 +173,11 @@
[:title (:title attrs)]
[:link {:rel "alternate" :type "application/atom+xml" :title "Atom" :href "http://4clojure.com/problems/rss"}]
[:link {:rel "shortcut icon" :href "/favicon.ico"}]
- (include-js "/vendor/script/jquery-1.5.2.min.js" "/vendor/script/jquery.dataTables.min.js")
- (include-js "/script/foreclojure.js")
- (include-js "/vendor/script/xregexp.js" "/vendor/script/shCore.js" "/vendor/script/shBrushClojure.js")
- (include-js "/vendor/script/ace/ace.js" "/vendor/script/ace/mode-clojure.js")
- (include-css "/css/style.css" "/css/demo_table.css" "/css/shCore.css" "/css/shThemeDefault.css")
+ (js "/vendor/script/jquery-1.5.2.min.js" "/vendor/script/jquery.dataTables.min.js")
+ (js "/script/foreclojure.js")
+ (js "/vendor/script/xregexp.js" "/vendor/script/shCore.js" "/vendor/script/shBrushClojure.js")
+ (js "/vendor/script/ace/ace.js" "/vendor/script/ace/mode-clojure.js")
+ (css "/css/style.css" "/css/demo_table.css" "/css/shCore.css" "/css/shThemeDefault.css")
[:style {:type "text/css"}
".syntaxhighlighter { overflow-y: hidden !important; }"]
[:script {:type "text/javascript"} "SyntaxHighlighter.all()"]]
@@ -1,20 +1,15 @@
(ns foreclojure.version
(:use [foreclojure.utils :only [def-page]]
[foreclojure.config :only [repo-url]]
- [compojure.core :only [defroutes GET]]
- [clojure.java.shell :only [sh]]))
-
-;; fetch this at load time rather than on demand, so that it's accurate even
-;; if someone checks out a different revision to poke at without restarting
-;; the server (eg to diagnose bugs in a release)
-(def sha (not-empty (:out (sh "git" "rev-parse" "--verify" "HEAD"))))
+ [foreclojure.git :only [sha]]
+ [compojure.core :only [defroutes GET]]))
(def-page version []
{:title "About/version"
:content
(if sha
[:p "SHA: "
- [:a {:href (str repo-url "/commit/" sha)} sha]]
+ [:a {:href (str repo-url "/tree/" sha)} sha]]
[:p "No git repository found"])})
(defroutes version-routes

0 comments on commit 2eb08ae

Please sign in to comment.