clojure - Compojure handler friend/authenticate eats body of POST request -
how can safely content of :body inputstream compojure?
see related different question background.
i'm trying authenticate ring routes friend using compojure handler/site when try read :body http post request (which java inputstream), closed:
23:01:20.505 error [io.undertow.request] (xnio-1 task-3) undertow request failed httpserverexchange{ post /paypal/ipn} java.io.ioexception: ut000034: stream closed @ io.undertow.io.undertowinputstream.read(undertowinputstream.java:84) ~[undertow-core-1.1.0.final.jar:1.1.0.final] @ sun.nio.cs.streamdecoder.readbytes(streamdecoder.java:284) ~[na:1.8.0_45] @ sun.nio.cs.streamdecoder.implread(streamdecoder.java:326) ~[na:1.8.0_45] @ sun.nio.cs.streamdecoder.read(streamdecoder.java:178) ~[na:1.8.0_45] @ java.io.inputstreamreader.read(inputstreamreader.java:184) ~[na:1.8.0_45] @ java.io.bufferedreader.fill(bufferedreader.java:161) ~[na:1.8.0_45] @ java.io.bufferedreader.read(bufferedreader.java:182) ~[na:1.8.0_45] @ clojure.core$slurp.doinvoke(core.clj:6650) ~[clojure-1.7.0-beta1.jar:na] @ clojure.lang.restfn.invoke(restfn.java:410) ~[clojure-1.7.0-beta1.jar:na] if remove handler, problem goes away. i've found 1 possible solution called groundhog captures , stores requests. library i'm using, clojure-paypal-ipn called reset on stream, not supported undertow (or indeed several other java/clojure servers), worked around it.
here a related discussion weavejester, author of compojure.
here snippets of code:
(defroutes routes ... (post "/paypal/ipn" [] (payment/paypal-ipn-handler payment/paypal-data payment/paypal-error paypal-sandbox?)) (route/resources "/")) (defn authenticate-routes "add friend handler routes" [routes-set] (handler/site (friend/authenticate routes-set friend-settings))) ;; middleware below immutant.web.middleware (defn -main [& {:as args}] (web/run (-> routes (web-middleware/wrap-session {:timeout 20}) (authenticate-routes) ; use friend handler ;; wrap handler websocket support ;; websocket requests go callbacks, ring requests handler (web-middleware/wrap-websocket websocket-callbacks)) args)) and here guts of payment.clj (paypal-data , paypal-error pprint input right now):
(defn req->body-str [req] "get request body ring post http request" (let [input-stream (:body req)] (let [raw-body-str (slurp input-stream)] raw-body-str))) (defn paypal-ipn-handler ([on-success on-failure] (paypal-ipn-handler on-success on-failure true)) ([on-success on-failure sandbox?] (fn [req] (let [body-str (req->body-str req) ipn-data (paypal/parse-paypal-ipn-string body-str)] (do (.start (thread. (fn [] (paypal/handle-ipn ipn-data on-success on-failure sandbox?)))) ; respond paypal right away, go , process ipn-data {:status 200 :headers {"content-type" "text/html"} :body ""})))))
Comments
Post a Comment