Как я высмеиваю JSON сообщение в ринге?

Я использую перидот - https://github.com/xeqi/peridot для тестирования моего кольцевого приложения, и он работает нормально, пока не попробую смоделировать почтовый запрос с данными json:

(требуется '[cheshire.core:as json])
(используйте 'compojure.core)

(defn JSON-Post [Req]
  (если (: требование к телу)
    (json / parse-string (slurp (:body req)))))

(размораживает все маршруты
  (POST "/test/json" req  (json-response (json-post req))))

(def app (compojure.handler/site all-routs))

(используйте 'peridot.core)

(-> (приложение сеанса)
    (запрос "/test/json":request-method:post:body (java.io.ByteArrayInputStream. (.getBytes "привет" "UTF-8")))

дает IOException: stream closed,

Есть лучший способ сделать это?

2 ответа

Решение

tldr:

(-> (session app)
    (request "/test/json"
             :request-method :post
             :content-type "application/json"
             :body (.getBytes "\"hello\"" "UTF-8")))

Когда перидот генерирует карту запроса, по умолчанию application/x-www-form-urlencoded для типа контента для :post запрос. С приложением, как указано wrap-params (который включен compojure.handler/site) попытаюсь прочитать :body чтобы проанализировать любые параметры, закодированные в форме. затем json-post попытки прочитать :body снова. тем не мение InputStreams предназначены для чтения один раз, и это вызывает исключение.

Есть два основных способа решения проблемы:

  1. Удалить compojure.handler/site,
  2. Добавить тип контента в запрос (как это сделано в tldr)
(require '[cheshire.core :as json])

(-> (session app)
    (request "/test/json"
             :request-method :post
             :content-type "application/json"
             :body (json/generate-string data))

Не нужно звонить .getBytesПросто передайте JSON с :body параметр.

Другие вопросы по тегам