Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I think you're stuck with some sort of "keep a copy around just in case" strategy. Unfortunately it looks like <code>:body</code> on the request <a href="https://github.com/ring-clojure/ring/blob/master/SPEC#L88" rel="nofollow noreferrer">must be an <code>InputStream</code></a> and nothing else (on the response it can be a <code>String</code> or other things which is why I mention it)</p> <p>Sketch: In a very early middleware, wrap the <code>:body</code> InputStream in an <code>InputStream</code> that resets itself on close (<a href="https://stackoverflow.com/a/925036/69689">example</a>). Not all <code>InputStream</code>s can be reset, so you may need to do some copying here. Once wrapped, the stream can be re-read on close, and you're good. There's memory risk here if you have giant requests.</p> <p>Update: here's an half-baked attempt, inspired in part by <code>tee-stream</code> in groundhog.</p> <pre><code>(require '[clojure.java.io :refer [copy]]) (defn wrap-resettable-body [handler] (fn [request] (let [orig-body (:body request) baos (java.io.ByteArrayOutputStream.) _ (copy orig-body baos) ba (.toByteArray baos) bais (java.io.ByteArrayInputStream. ba) ;; bais doesn't need to be closed, and supports resetting, so wrap it ;; in a delegating proxy that calls its reset when closed. resettable (proxy [java.io.InputStream] [] (available [] (.available bais)) (close [] (.reset bais)) (mark [read-limit] (.mark bais read-limit)) (markSupported [] (.markSupported bais)) ;; exercise to reader: proxy with overloaded methods... ;; (read [] (.read bais)) (read [b off len] (.read bais b off len)) (reset [] (.reset bais)) (skip [n] (.skip bais))) updated-req (assoc request :body resettable)] (handler updated-req)))) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload