Closing a served file in clojure/webnoir

251 Views Asked by At

I've got the following function in webnoir that serves up an image from disk.

(defpage [:get "/GetPhoto"] {:keys [photoName]}
         (def file (io/input-stream  (str photoName ".jpg")))
         (resp/set-headers {"Content-Type" "image/jpeg"} file))

I assume I should close the file, but when I add (.close file) to the end of the function, I get an error java.io.IOException: Stream closed when accessing the URL. What's the right way to handle this?

2

There are 2 best solutions below

1
On BEST ANSWER

Obviously you can't close the file at the end of the function, because all you do with noir/ring is to return a data structure describing the response. Ring then uses this data structure to actually respond to the client. In this case it sees a stream and tries to read from it. When you close it (explicit or with with-open) this will fail.

I would expect you don't have to do anything and ring will close the stream after exhausting it.

You don't want nested def. You don't want nested def. You don't want nested def. You don't want...

2
On

The def on line two is very likely not what you want. I would recommend replacing it with a with-open statement. This is defining a new symbol for the whole namespace each time this function runs. As a general rule calls to def are used at the top level or inside a macro.

(defpage [:get "/GetPhoto"] {:keys [photoName]}
         (with-open [file (io/input-stream  (str photoName ".jpg"))]
           (resp/set-headers {"Content-Type" "image/jpeg"} file))