This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-09
Channels
- # aleph (1)
- # announcements (7)
- # asami (1)
- # beginners (44)
- # calva (54)
- # cherry (24)
- # cider (6)
- # clj-kondo (19)
- # cljsrn (27)
- # clojure (119)
- # clojure-europe (61)
- # clojure-gamedev (38)
- # clojure-germany (7)
- # clojure-nl (1)
- # clojure-norway (104)
- # clojure-portugal (4)
- # clojure-spec (4)
- # clojure-uk (1)
- # clojurescript (38)
- # cursive (18)
- # datomic (11)
- # emacs (9)
- # events (1)
- # fulcro (4)
- # holy-lambda (7)
- # introduce-yourself (7)
- # jobs (1)
- # malli (6)
- # off-topic (4)
- # pathom (4)
- # pedestal (16)
- # podcasts-discuss (1)
- # polylith (27)
- # portal (17)
- # releases (2)
- # shadow-cljs (46)
- # squint (1)
- # xtdb (9)
Can we somehow make resources / static content work like most other static content servers like nginx where
serves
in pedestal?
I went down the rabbit hole.
Seems that by default pedestal uses both content-type
and file-path
middleware / interceptors from ring:
https://github.com/pedestal/pedestal/blob/0.5.10/service/src/io/pedestal/http.clj#L260
https://github.com/pedestal/pedestal/blob/0.5.10/service/src/io/pedestal/http.clj#L268
defined here:
https://github.com/pedestal/pedestal/blob/0.5.10/service/src/io/pedestal/http/ring_middlewares.clj#L69
https://github.com/pedestal/pedestal/blob/0.5.10/service/src/io/pedestal/http/ring_middlewares.clj#L81
which lead inside ring:
https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/middleware/content_type.clj#L6
https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/middleware/file.clj#L19
https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/util/response.clj#L148
Using ::http/file-path
to enable the default file
pedestal interceptor by e.g. specifying ::http/file-path "resources/public/"
works, but not as expected. It now serves files from given directory, but with a content-type response of application/octet-stream
which leads to the html file being downloaded instead of presented by the browser
Check out the fast-resource interceptor. https://github.com/pedestal/pedestal/blob/master/service/src/io/pedestal/http/ring_middlewares.clj#L148
I removed ::http/resource-path to disable default resource interceptor and added a route like:
["/" :get [(middleware/fast-resource "/public")]]
inspected the service map just to make sure, and same result: while I get the index.html back in the response, the content type is set to application/octet-stream and this leads to a downloadah, yes. i remember now. the content-type ring middleware only sets the content type based on the request uri. it does not look at the file extension. theres an issue and a PR that fixes this in the ring repo, but alas, its not merged. https://github.com/ring-clojure/ring/issues/408 https://github.com/ring-clojure/ring/pull/452 we ended up doing this at work: `(defn content-type-interceptor [] (after ::content-type-interceptor (fn [ctx] (let [uri (get-in ctx [:request :uri]) resp (:response ctx)] (if-let [mime-type (or (get-in ctx [:response :headers "Content-Type"]) (mime/ext-mime-type uri) ;; Additional check compared to io.pedestal.http.ring-middlewares/content-type ;; Workaround for problem described here: https://github.com/ring-clojure/ring/issues/408 (when (instance? File (:body resp)) (mime/ext-mime-type (.getAbsolutePath (:body resp)))) ;; Same problem as above, when all else fails. Look for a hint in the context map. (when (::mime-lookup ctx) (mime/ext-mime-type (::mime-lookup ctx))))] (assoc-in ctx [:response :headers "Content-Type"] mime-type) ctx)))))`
I think that does the trick, although I would love this functionality to be supported upstream
Is there something in pedestal which lets me define an interceptor which is executed before every other interceptor in the chain? (I want to tap>
the interceptor :name
and context for debugging purposes) 🙂.
{::interceptor-name :my-interceptor
::input-context context}
No, but that should be fairly straight forward to create: 1 map :name over your chain 2 instantiate the "tapping" interceptor for each name 3 interleave those with your original chain
I think metosin has something like this, maybe in reitit, that will also run diff on the context to highlight whats changed.
Thanks for the ideas, very much appreciated!