How can I generate modified http headers using Compojure?

I am trying to improve performance for clients receiving pages from my Compojure web server. We serve a bunch of static files (JS, CSS) with (compojure.route/resources "/") , which searches for files in the file system, converts them to URLs and then treats them as Ring as streams. When converting to streams, it seems to lose all file metadata, such as time in mod mode.

I can wrap the static resource handler and add the Expires or Cache-Control: max-age header, but this prevents the client from sending the request at all. Useful, but these files sometimes change (when we release).

Ideally, I would like the client to trust its own cached version, for example, in an hour, and make a request with an If-Modified-Since header after that hour has passed. Then we can simply return 304 Not Modified , and the client avoids loading a couple of hundred kilograms of javascript.

It looks like I can set the Last-Modified header when serving the response, and this forces the client to qualify subsequent requests with If-Modified-Since headers. Great, except that I would have to rewrite most of the code in compojure.route/resources to add Last-Modified - not difficult, but tedious - and come up with another code to recognize and respond to the If-Modified-Since header. Not a monumental task, but also not a simple one.

Does it already exist somewhere? I could not find it, but it seems common enough and big enough, for someone to write a library for him by now.

+4
source share
2 answers

FWIW, I got this to work using Ring wrap-file-info middleware; I am confused by looking for this in Compojure instead of Ring. However, the compojure.route files and resources handlers serve streams instead of files or URLs, and, of course, Ring cannot determine the metadata from this.

I had to write a basically copy of resources that returns File ; when it is wrapped in wrap-file-info , which met my needs. All the same, I would not mind a slightly better solution that is not related to copying a piece of code from Compojure.

+4
source

Do you find using ring-etag-middleware ? It uses the last modified file date to generate an object tag. Then it calls 304 according to the if-none-match header in the request.

+1
source

All Articles