2

我正在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..."我在命令行 ( )生成了base64 字符串,cat original.gif | base64所以知道那里没有问题
  3. 当像素发送成功时,我已经验证了它的内容是正确的 ( diff original.gif received-pixel.gif)

我是 Clojure 的新手——我猜我的代码中有一些令人尴尬的动态 gremlin,但我需要帮助来发现它!

4

2 回答 2

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)}))
于 2012-10-30T14:17:21.557 回答
0

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

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

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

它也处理不存在的文件。另请参阅文档

于 2017-12-14T13:55:55.280 回答