               asset-pipeline (:asset-pipeline context)]
           (create-asset-response path-prefix
                                  requested-checksum
-                                 (asset-pipeline asset-path context')))))))
+                                 (asset-pipeline asset-path context')
+                                 attachment-name))))))
 
 ;;; It's really difficult to start with a path, convert it to a resource, and figure out if it is a folder
 ;;; or a file on the classpath. Instead, we just assume that anything that doesn't look like a path that

      .getTime))

(defn- asset->ring-response
  [asset]
  (cond->
    ;; First the standard stuff ...
    (-> asset
        :content
        io/input-stream
        r/response
        (r/header "Content-Length" (:size asset))
        ;; Because any change to the content will create a new checksum and a new URL, a change to the content
        ;; is really an entirely new resource. The current resource is therefore immutable and can have a far-future expires
        ;; header.
        (r/header "Expires" far-future)
        (r/content-type (:content-type asset)))
    ;; The optional extras ...
    (:compressed asset) (r/header "Content-Encoding" "gzip")))


(defn- match? [^String path-prefix ^String path]

(def ^:private asset->301-response (partial asset->redirect-response 301))

(defn- create-asset-response
  [path-prefix requested-checksum asset attachment-name]
  (cond
    (nil? asset) nil
    (= requested-checksum (:checksum asset)) (asset->ring-response asset attachment-name)
    :else (asset->301-response path-prefix asset)))

(defn twixt-handler
  "A Ring request handler that identifies requests targetted for Twixt assets.  Returns a Ring response map
   if the request is for an existing asset, otherwise returns nil.

   The path may indicate an attachment to the asset (such as the source.map for a compiled JavaScript file).
   The attachment is indicated as a suffix: the `@` symbol and the name of the attachment.

   Asset URLs always include the intended asset's checksum; if the actual asset checksum does not match, then
   a 301 (moved permanently) response is sent with the correct asset URL."
  [request]
  (let [path-prefix (-> request :twixt :path-prefix)
        path (:uri request)]
    (when (match? path-prefix path)
      (t/track
        #(format "Handling asset request `%s'" path)
        (let [[requested-checksum compressed? asset-path attachment-name] (parse-path path-prefix path)
              context (:twixt request)
              ;; When actually servicing an asset request, we have to trust the data in the URL
              ;; that determines whether to server the normal or gzip'ed resource.
