Robin Carlo Catacutan
Robin Carlo Catacutan

Reputation: 13679

Serve static favicon file in Compojure

According to Compojure:

Compojure does not serve static files by default, nor does it automatically deal out 404s when no route matches.

So to deal with that, we have to set these Public Vars

And this is how we currently set it:

(defroutes app-routes
  (route/files "/" {:root "path/to/public"})
  (route/resources "/")
  (route/not-found "Not Found"))

It worked as expected when most of the static files are accessed through the web browser.

e.g.

http://localhost:3000/img/icon.png

But the problem is, it doesn't work on favicon files.

e.g.

http://localhost:3000/img/favicon.ico

It treats this as a different call which it should be serve as a static file.

Response to to the CURL I run:

* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /img/favicon.ico HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost:3000
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 28 Jul 2015 19:05:24 GMT
< Last-Modified: Thu, 28 May 2015 14:51:16 +0000
< Content-Length: 1106
< Content-Type: image/x-icon
* Server Jetty(7.6.13.v20130916) is not blacklisted
< Server: Jetty(7.6.13.v20130916)

Upvotes: 1

Views: 1004

Answers (2)

rezwits
rezwits

Reputation: 872

umm...

This works for me, (wherever you define/declare your routes):

In the namespace section:

            [ring.util.response :refer [resource-response]]

Down below (at least above (def app ):

(defn wrap-return-favicon [handler]
  (fn [req]
    (if (= [:get "/favicon.ico"] [(:request-method req) (:uri req)])
      (resource-response "favicon.ico" {:root "public/img"})
      (handler req))))

then in:

(def app
  (-> routes
      ...
      wrap-return-favicon
      wrap-stacktrace))

Upvotes: 0

Nathan Davis
Nathan Davis

Reputation: 5766

files, resources, and not-found are functions, not variables that you set. When you call (route/files "/" {:root "path/to/public"}), a route for resolving URLs under "/" as static files under "path/to/public" is returned.

defroutes defines a collection of routes. These routes are tried in the order they are listed, until the first one that returns a response.

If you add a route (GET "/:slug" [* :as req slug] (search req slug)) before the others, then any URL other than "/" will be handled by this new route — including the favicon request. On the other hand, if you add it just before the not-found route, then it should work.

Also, if there isn't a static file that matches the request, then the files route will fail and the next one will be tried. So you should also check that favicon.ico actually exists and is in the img sub-directory.

Upvotes: 3

Related Questions