Created
March 9, 2017 14:46
-
-
Save mtnygard/586f4681b0850adb3be0923c54f74bc4 to your computer and use it in GitHub Desktop.
Access CLJSJS assets via a Pedestal Interceptor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns overt.cljsjs | |
(:require [clojure.java.io :as io] | |
[io.pedestal.interceptor :as i] | |
[io.pedestal.log :as log]) | |
(:import java.net.URL | |
java.util.Date | |
java.util.jar.JarFile)) | |
(def ^:private default-base "cljsjs") | |
(defn- asset-headers | |
[asset-info] | |
{"Content-Length" (str (:content-length asset-info))}) | |
(defn- last-modified | |
[cxn] | |
(let [ts (.getLastModified cxn)] | |
(when-not (zero? ts) | |
(Date. ts)))) | |
(defn- asset-info | |
[path] | |
(when-let [url (io/resource path)] | |
(when-let [cxn (.openConnection url)] | |
{:contents (.getInputStream cxn) | |
:content-length (.getContentLength cxn) | |
:last-modified (last-modified cxn)}))) | |
(defn- serve-asset | |
[ctx path] | |
(if-let [info (asset-info path)] | |
(assoc ctx :response | |
{:status 200 | |
:body (:contents info) | |
:headers (asset-headers info)}) | |
ctx)) | |
(defn resources-containing | |
[fragment] | |
(enumeration-seq | |
(.. (Thread/currentThread) getContextClassLoader (getResources fragment)))) | |
(defn jar? | |
[^URL url] | |
(= "jar" (.getProtocol url))) | |
(defn expand-entries | |
[jar-url] | |
(let [[_ jar] (re-find #"^file:(.*\.jar)\!.*$" (.getPath jar-url))] | |
(enumeration-seq (.entries (JarFile. (io/file jar)))))) | |
(defn directory? | |
[jar-entry] | |
(.isDirectory jar-entry)) | |
(defn cljsjs-asset? | |
[jar-entry] | |
(.startsWith (.getName jar-entry) "cljsjs")) | |
(defn entry-name | |
[jar-entry] | |
(.getName jar-entry)) | |
(def jar-entry-names | |
(comp | |
(filter jar?) | |
(mapcat expand-entries) | |
(remove directory?) | |
(filter cljsjs-asset?) | |
(map entry-name))) | |
(defn index-assets | |
[base] | |
(into #{} | |
jar-entry-names | |
(resources-containing base))) | |
(defn assets | |
([] | |
(assets default-base)) | |
([base] | |
(let [index (index-assets base)] | |
{:name ::assets | |
:enter | |
(fn [ctx] | |
(log/info :cljsjs/assets true) | |
(let [request-path (subs (-> ctx :request :path-info) 1)] | |
(log/info :request-path request-path :in-index? (contains? index request-path)) | |
(if (contains? index request-path) | |
(serve-asset ctx request-path) | |
ctx)))}))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment