I'm trying to improve performance for clients fetching pages from my Compojure webserver. We serve up a bunch of static files (JS, CSS) using (compojure.route/resources "/")
, which looks for files on the filesystem, converts them to URLs, and then serves them to Ring as streams. By converting to streams, it seems to lose all file metadata, such as the mod time.
I can wrap the static-resource handler and add an Expires
or Cache-Control: max-age
header, but that prevents the client from sending any request at all. Useful, but these files do change on occasion (when we put out a release).
Ideally I'd like the client to trust its own cached version for, say, an hour, and make a request with an If-Modified-Since
header after that hour has passed. Then we can just return 304 Not Modified
and the client avoids downloading a couple hundred kilos of javascript.
It looks like I can set a Last-Modified
header when serving a response, and that causes the client to qualify subsequent requests with If-Modified-Since
headers. Great, except I'd have to rewrite most of the code in compojure.route/resources
in order to add Last-Modified
- not difficult, but tedious - and invent some more code to recognize and respond to the If-Modified-Since
header. Not a monumental task, but not a simple one either.
Does this already exist somewhere? I couldn't find it, but it seems like a common enough, and large enough, task that someone would have written a library for it by now.