2013-06-11 7 views
8

Ich bin mit Peridot - https://github.com/xeqi/peridot meinen Ring Anwendung zu testen, und seine Arbeit gut, bis ich versuche, eine Post-Anforderung mit JSON-Daten zu verspotten:Wie spot ich eine JSON Post Anfrage im Ring?

 
(require '[cheshire.core :as json]) 
(use 'compojure.core) 

(defn json-post [req] 
    (if (:body req) 
    (json/parse-string (slurp (:body req))))) 

(defroutes all-routes 
    (POST "/test/json" req (json-response (json-post req)))) 

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

(use 'peridot.core) 

(-> (session app) 
    (request "/test/json" 
      :request-method :post 
      :body (java.io.ByteArrayInputStream. (.getBytes "hello" "UTF-8"))) 

gibt IOException: stream closed.

Gibt es einen besseren Weg, dies zu tun?

Antwort

9

TLDR:

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

Wenn Peridot eine Anfrage Karte erzeugt es application/x-www-form-urlencoded für die Content-Type für eine :post Anforderung nicht erfüllt. Mit der App wrap-params (die von compojure.handler/site enthalten ist) wird versucht, die :body zu lesen, um alle Form-urlencoded Parameter zu analysieren. Dann versucht json-post die :body wieder zu lesen. InputStream s sind jedoch so konzipiert, dass sie nur einmal gelesen werden und die Ausnahme verursachen.

Es gibt grundsätzlich zwei Möglichkeiten, das Problem zu lösen:

  1. compojure.handler/site entfernen.
  2. einen Inhaltstyp auf die Anfrage hinzufügen (wie in der TLDR getan)
4
(require '[cheshire.core :as json]) 

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

Keine Notwendigkeit .getBytes zu nennen, nur json mit :body Parameter.