1
votes

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

  • files
  • not-found
  • resources

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)
2
Paste the response to a curl -vvv http://localhost:3000/img/favicon.ico please - Jaime Agudo
@JamesSharp I have posted the response. - Robin Carlo Catacutan
It seems ok... why do you say it doesn't work? If you are testing with a browser its cache may be messing up but it does have nothing to do with compojure. Have a look - Jaime Agudo
It loads the favicon but when I said it doesn't work I mean the compojure "I believe" didn't served it as a static file but instead it treats it like one of the routes. So it's like it fall under this route: (GET "/:slug" [* :as req slug] (search req slug)) - Robin Carlo Catacutan

2 Answers

3
votes

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.

0
votes

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))