我认为我做对了,但我无法从 :body 输入流中获取我的 EDN。 Ring 和 Compojure 处理程序是这样的:

依赖:

 [ring.middleware.params :as params]
 [ring.middleware.edn :as edn]; https://github.com/tailrecursion/ring-edn

处理程序:
(defroutes ajax-example
  (PUT "/ajax-example" r
       (println r)
       {:status 200
        :headers {"Content-Type" "application/edn"}
        :body "yo"}))

我把它包装成:
  (def ajax-wrapped
   (-> ajax-example
      edn/wrap-edn-params
      params/wrap-params))
println 的响应正确地表明它是 EDN 并且根据我发送的简单测试 map 内容长度是正确的,但是 map 本身无处可寻,它永远被困在 :body 的输入流中。 . 怎么弄呢?

这是响应 println:

{:ssl-client-cert nil, :remote-addr 0:0:0:0:0:0:0:1, :params {}, :route-params {}, :headers {origin http://localhost:6542 , host localhost: 6542, 用户代理 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36, 内容类型应用程序/edn, cookie _ga=GA18252144882516 ;内容长度 20,引用 http://localhost:6542/,连接保持事件,接受/,接受语言 en-US,en;q=0.8,sq;q=0.6,接受编码 gzip,deflate,sdch,缓存控制 max-age =0}, :server-port 6542, :content-length 20, :form-params {}, :query-params {}, :content-type application/edn, :character-encoding nil, :uri/ajax-example , :server-name localhost, :query-string nil, :body #, :edn-params nil, :scheme :http, :request-method :put}

:body 上面没有正确粘贴,它看起来像这样:
 [open corner bracket] HttpInput org.eclipse.jetty.server.HttpInput@5d969109 [end corner bracket]

使用 cljs-ajax lib 从浏览器发送的客户端代码是:
(defn ajax-send
  []
  (let [push {:adder1 2 :add2 3}]
    (PUT "/ajax-example"
         {:format :edn
          :params push
          :handler ajax-result
          :error-handler error-handler})))

以下是其中一个答案建议的测试输出:
hf.examples> ((-> ajax-example  params/wrap-params edn/wrap-edn-params) (-> (mock/request :put "/ajax-example")
                                                             (mock/content-type "application/edn")
                                                             (mock/body "{:hello \"there\"}")))
{:status 200,
 :headers {"Content-Type" "application/edn"},
 :body
 "{:remote-addr \"localhost\", :params {:hello \"there\"}, :route-params {}, :headers {\"content-length\" \"16\", \"content-type\" \"application/edn\", \"host\" \"localhost\"}, :server-port 80, :content-length 16, :form-params {}, :query-params {}, :content-type \"application/edn\", :uri \"/ajax-example\", :server-name \"localhost\", :query-string nil, :edn-params {:hello \"there\"}, :scheme :http, :request-method :put}"}
hf.examples>

我也试过这个:
(defroutes ajax-example
  (PUT "/ajax-example" r
       {:status 200
        :headers {"Content-Type" "application/edn"}
        :body (pr-str (dissoc r :body))}))

curl 结果独立于前端:
curl -X PUT -H "Content-Type: application/edn" -d '{:name :barnabas}' http://localhost:6542/ajax-example
{:ssl-client-cert nil, :remote-addr "0:0:0:0:0:0:0:1", :params {}, :route-params {}, :headers {"host" "localhost:6542", "content-length" "17", "content-type" "application/edn", "user-agent" "curl/7.37.1", "accept" "*/*"}, :server-port 6542, :content-length 17, :content-type "application/edn", :character-encoding nil, :uri "/ajax-example", :server-name "localhost", :query-string nil, :edn-params nil, :scheme :http, :request-method

17 的 content-length 匹配通过 Curl 传递的 map 中的字符数。但是 edn-params 为零!内容在哪里?

最佳答案

编辑 :作为对更新问题的回答,wrap-edn-params 函数通过完全读取 :body InputStream 来消耗请求的主体。 Compojure 路由将请求传递给每个参数处理程序,直到返回非 nil 值。在这种情况下,作为第一个处理程序传递给路由的处理程序将消耗 :body 并且将没有 :body 值供第二个处理程序消耗,从而导致 wrap-edn-params 读取的正文值为零。

传递给环处理程序的请求可能没有将其内容类型设置为 edn。如果请求内容类型设置为 edn,wrap-edn-params function 将仅解析 edn。

此外,解析的 edn 参数将仅被 wrap-edn-params 函数放置在请求映射的 :params 和 :edn-params 键中,因此不应使用 :body 访问解析的 edn。

(require '[ring.mock.request :as mock])
(require '[ring.middleware.edn :as edn])

((-> ajax-example  params/wrap-params edn/wrap-edn-params) (-> (mock/request :put "/ajax-example")
                                                             (mock/content-type "application/edn")
                                                             (mock/body "{:hello \"there\"}")))

{:remote-addr "localhost",
 :params {:hello "there"},
 :route-params {},
 :headers
 {"content-length" "16",
  "content-type" "application/edn",
  "host" "localhost"},
 :server-port 80,
 :content-length 16,
 :form-params {},
 :query-params {},
 :content-type "application/edn",
 :uri "/ajax-example",
 :server-name "localhost",
 :query-string nil,
 :body #<ByteArrayInputStream java.io.ByteArrayInputStream@171788d8>,
 :edn-params {:hello "there"},
 :scheme :http,
 :request-method :put}

关于clojure - 无法解析出此服务器请求中的 EDN,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30209769/

10-12 01:30