ring-json的wrap-json-response中间件和compojure返回text/plain?

12

我试图在我的 compojure 应用程序中使用 ring-json 的 wrap-json-response 中间件。我有一个简单的 GET 处理程序,返回类似 {:foo 1} 的映射,当我访问 URL 时,ring 响应 text/plain 和空响应体。我似乎无法让它响应地图的 JSON 版本。

这是我的处理程序代码:

(ns localshop.handler
  (:use compojure.core)
  (:require [localshop.routes.api.items :as routes-api-items]
            [ring.middleware.json :as middleware]
            [compojure.handler :as handler]
            [compojure.route :as route]))

;; map the route handlers
(defroutes app-routes
  (context "/api/item" [] routes-api-items/routes))

;; define the ring application
(def app
  (-> (handler/api app-routes)
      (middleware/wrap-json-body)
      (middleware/wrap-json-params)
      (middleware/wrap-json-response)))

路由处理函数实际上只返回一个映射,因此代码简单到我认为可以省略。如果从compojure路由处理程序返回映射是问题所在,那么也许就是这个问题了?

2个回答

16

查看这里。基本上,如果您返回{:body {:my-map "hello"}},它将正常工作。


3
谢谢你的答案,我差点把头发都拔光了。这个应该有更好的文档记录。 - jd.
为什么它必须包含在 :body 内? - Teo Choong Ping
2
我最好的猜测是因为该方法可以允许除响应主体之外的更多选项,所以它要求您隐式指定 {:body {}} - film42
需要这样做的原因是Compojure和Ring(隐式地)期望HTTP响应。它们自动处理简单类型的事实是混淆的根源。请参见我的答案以及一个有点相关的问题 - Kenny Evitt
你指的是哪个提交哈希值? - opyate
默认情况下,字符串将被转换为响应 {:status 200, :body string}。但是,您的处理程序可能希望显式地返回其他有趣属性的响应,例如不同于 200(400、301 等)的状态代码、有趣的标头等等。由于响应也只是一个映射,如果所有映射都被视为 OK JSON 响应的主体,则这将是不可能的。 - ealfonso

1

在编写REST API时,我遇到了类似的问题。

当处理程序返回向量时,我会收到异常,即在compojure中的Renderable协议中没有PersistentVector方法的实现。

当返回映射时,头部为空。

当返回序列时,我得到了'text/html'。

因此,我认为在我们的代码中扩展Renderable是一个很好的解决方案:这真是clojure的一份不错的礼物。

但是,作为快速解决方案的hack,我使用了下一个中间件:

(defn wrap-content-json [h]
  (fn [req] (assoc-in (h req) [:headers "Content-Type"] "application/json")))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接