[SOLVED] `ionize` does not handle responses with a :body of type File

I’m deploying a backend as a web ion that uses the ring.middleware.defaults/site-defaults middleware. The middleware includes the ring.middleware.resource middleware to serve files from my resources/public/ directory. This worked fine locally, but when I deployed to Datomic Cloud and hit an endpoint that should serve up the contents of a file, I instead got an error response with the following body:

error: No implementation of method: :->bbuf of protocol: #'datomic.ion.lambda.api-gateway/ToBbuf found for class: java.io.File

I was confused about this, because according to the Ions Reference, lambda ions should handle responses whose body is a File. My confusion, I now realize, is that the datomic.ion.lambda.api-gateway/ionize function does not create a lambda ion, at least not in every sense. Rather, I have a web ion, and I’m using ionize to publish it.

In other words, after reading the documentation more carefully, I’m backing down from my original belief that the linked Ion Reference page was incorrect. :slight_smile:

Anyway, the fix for me, in case it’s useful to anybody else, was to replace the <original-return-value> of the handler that I pass to ionize with something more like this:

(let [response <original-return-value>]
  (if (instance? java.io.File (:body response))
    (update response :body slurp)
    response))

Hope this helps somebody. :beer:

1 Like

For the benefit of folks searching and landing here, what you want to do is:

(if (instance? java.io.File (:body response))
  (update response :body clojure.java.io/input-stream)
  response)

i.e. io/input-stream not slurp, partly because you don’t want to be reading everything into memory, but more importantly, slurp seems to mess up images, presumably because it’s intended for text data, not binary. Thanks to @stu for the tip.

3 Likes