Serving static file bug ? (minor)

61 views
Skip to first unread message

Vagif Verdi

unread,
Jun 25, 2009, 12:43:52 PM6/25/09
to Compojure
When trying to reach non existent file with image extention (jpg, gif,
png etc)
it returns text: "http://localhost:8080/blabla.jpg" instead of falling
to 404 page.


James Reeves

unread,
Jun 25, 2009, 3:18:29 PM6/25/09
to Compojure
Have you configured it to fall to a 404 page? Compojure is very
explicit; it only does what you tell it to do.

(defroutes file-handler
(GET "/*"
(or (serve-file (params :*))
:next))
(ANY "*"
(page-not-found)))

- James

Vagif Verdi

unread,
Jun 25, 2009, 5:47:39 PM6/25/09
to Compojure
On Jun 25, 11:18 am, James Reeves <weavejes...@googlemail.com> wrote:

> Have you configured it to fall to a 404 page? Compojure is very
> explicit; it only does what you tell it to do.
>
> (defroutes file-handler
>   (GET "/*"
>     (or (serve-file (params :*))
>         :next))
>   (ANY "*"
>     (page-not-found)))

Yes, i did just that. In fact for files with extention htm, html etc,
it falls to 404 properly. But for image types not.

Now thinking about it, maybe it is not a bug but a feature. What would
browser do with 404 page instead of an image ?

James Reeves

unread,
Jun 25, 2009, 6:04:49 PM6/25/09
to Compojure
On Jun 25, 10:47 pm, Vagif Verdi <Vagif.Ve...@gmail.com> wrote:
> Yes, i did just that. In fact for files with extention htm, html etc,
> it falls to 404 properly. But for image types not.

It works okay on my browser. Perhaps it's got something to do with the
content type. Try:

(defroutes site
(GET "/*"
(or (serve-file (params :*))
:next))
(ANY "*"
[(content-type "text/html")
(page-not-found)]))

Compojure currently leaves setting the mimetype up to the user, or for
the browser to guess.

What Compojure probably needs is some middleware to guess the mime
type from the extension. So if the URI ends in ".png", it knows to set
the content-type header to "image/png". Perhaps the user can specify a
Clojure map of extension->mimetype mappings as an argument.

- James

Mark McGranaghan

unread,
Jun 26, 2009, 8:08:51 AM6/26/09
to Compojure

radu.floricica

unread,
Jun 29, 2009, 4:26:05 PM6/29/09
to Compojure

A bit of googling got me to this thread. I got a similar problem with
css in Chrome: until I specified the mime-type as text/css chrome
refused to acknowledge the css:

(GET "/style.css" (or (with-headers (fn [request] {:body (serve-file
"style.css")}) {"Content-Type" "text/css"}) "CSS file not found"))

Html: <link href="/style.css" rel="stylesheet" type="text/css" />


Same thing with a javascript library (tiny_mce), but this one needed
to get right several mime types so I had to hack a dirty guess-mime.

(defn guess-mime [name]
(cond
(.endsWith (.toLowerCase name) ".css") "text/css"
(.endsWith (.toLowerCase name) ".js") "text/javascript"
(.endsWith (.toLowerCase name) ".html") "text/html"
(.endsWith (.toLowerCase name) ".htm") "text/html"
(.endsWith (.toLowerCase name) ".txt") "text/plain"
true nil))

Now it works fine.

James Reeves

unread,
Jun 29, 2009, 5:21:09 PM6/29/09
to Compojure
On Jun 29, 9:26 pm, "radu.floricica" <radu.floric...@gmail.com> wrote:
> (GET "/style.css" (or (with-headers (fn [request] {:body (serve-file
> "style.css")}) {"Content-Type" "text/css"}) "CSS file not found"))

You could also write:

(GET "/style.css"
[(content-type "text/css")
(file "/style.css")])

But we probably want some middleware to handle this, so that we can
write:

(decorate your-routes
(with-mimetypes
{"txt" "text/plain"
"png" "image/png"
"js" "text/javascript"}))

I'll raise an issue for it.

Alternatively you could use Mark's ring.file-info functions. Hm,
perhaps we need to consolidate common middleware in the Ring and
Compojure namespaces.

- James

Mark McGranaghan

unread,
Jun 30, 2009, 11:13:33 AM6/30/09
to Compojure
I quietly updated ring.file-info a while back to be able to handle
custom mimetypes like the ones described above. In particular:

(defn my-core-app [req] ...)

(def my-custom-mimetypes
{"txt" "text/plain"
"png" "image/png"
"js" "text/javascript"})

(def my-app (ring.file-info/wrap my-custom-mimetypes my-core-app))

These types are all in the default mimetype map in ring.file-info, so
you really could just do

(def my-app (ring.file-info/wrap my-core-app))

James, what exactly were you thinking about in terms of consolidating
middleware? It would be a shame to have stuff like this implemented
twice; one of the main benefits or using Ring is that everyone -
Compojure users and otherwise - can share middleware.

- Mark

James Reeves

unread,
Jun 30, 2009, 4:04:13 PM6/30/09
to Compojure
On Jun 30, 4:13 pm, Mark McGranaghan <mmcgr...@gmail.com> wrote:
> I quietly updated ring.file-info a while back to be able to handle
> custom mimetypes like the ones described above.

Ah, I didn't realise that. Though I was also thinking about the
possibility of middleware overlapping.

> James, what exactly were you thinking about in terms of consolidating
> middleware? It would be a shame to have stuff like this implemented
> twice; one of the main benefits or using Ring is that everyone -
> Compojure users and otherwise - can share middleware.

Those are my thoughts too. I was hoping we could reach a consensus
between the style of middleware in the Ring namespace:

(middleware-type/wrap options... handler)

And the style in Compojure:

(with-middleware-type handler options...)

Then we could start consolidating middleware and other useful
functions into Ring. Parts of Compojure are generic enough that
perhaps other frameworks would benefit from them.

Do you mind if I email you some suggestions? Obviously we're two
different programmers and won't agree on everything, but hopefully we
can create a strong basis for people to base their web frameworks and
libraries on, whilst being careful to remain generic enough to
accommodate any style of framework.

- James
Reply all
Reply to author
Forward
0 new messages