使用Clojure / Ring为二进制文件提供间歇性错误

时间:2012-10-30 14:13:49

标签: clojure ring

我正在为event collector in Clojure构建Snowplow(使用Ring / Compojure),并且在使用Ring提供透明像素时遇到一些问题。这是我发送像素的代码:

(ns snowplow.clojure-collector.responses
  (:import (org.apache.commons.codec.binary Base64)
           (java.io ByteArrayInputStream)))

(def pixel-bytes (Base64/decodeBase64 (.getBytes "R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==")))
(def pixel (ByteArrayInputStream. pixel-bytes))

(defn send-pixel
   []
    {:status  200
     :headers {"Content-Type"   "image/gif"}
     :body    pixel})

当我启动服务器时,第一次点击send-pixel的路径时,像素已成功传送到我的浏览器。但是第二次 - 以及每次之后 - Ring都没有发送正文(内容长度为0)。重启服务器,它的模式相同。

有些事情不是:

  1. 我使用wget复制了此内容,以确认间歇性不是浏览器缓存问题
  2. 我在命令行("R01GOD...")生成了cat original.gif | base64 base64字符串,所以知道那里没有问题
  3. 成功发送像素后,我已验证其内容是否正确(diff original.gif received-pixel.gif
  4. 我是Clojure的新手 - 我猜我的代码中有一些令人尴尬的动态gremlin,但我需要帮助发现它!

2 个答案:

答案 0 :(得分:6)

我在发布后不久发现了REPL中的问题:

user=> (import (org.apache.commons.codec.binary Base64) (java.io ByteArrayInputStream))
java.io.ByteArrayInputStream
user=> (def pixel-bytes (Base64/decodeBase64 (.getBytes "R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==")))
#'user/pixel-bytes
user=> (def pixel (ByteArrayInputStream. pixel-bytes))
#'user/pixel
user=> (slurp pixel-bytes)
"GIF89a!�\n,L;"
user=> (slurp pixel-bytes)
"GIF89a!�\n,L;"
user=> (slurp pixel)
"GIF89a!�\n,L;"
user=> (slurp pixel)
""

所以基本上问题是ByteArrayInputStream在第一次通话后被清空了。可变数据结构!

我通过为每个响应生成一个新的ByteArrayInputStream来修复错误,其中包含:

    :body    (ByteArrayInputStream. pixel-bytes)}))

答案 1 :(得分:0)

问题是您的pixel变量包含一个流。一旦读完,就不可能再次重读。

此外,您不需要处理编码问题。 Ring也提供静态文件。回来:

(file-response "/path/to/pixel.gif")

它也处理不存在的文件。 See the docs也是。