   by single use or composition."
   (:require
    [cheshire.core :as json]
+   [cheshire.generate :as json-gen]
    [clojure.data.xml :as xml]
    [clojure.string :as string]
+   [cmr.exchange.common.results.errors :as errors]
    [ring.util.http-response :as response]
    [taoensso.timbre :as log]
    [xml-in.core :as xml-in])
+  (:import
+    (java.lang.ref SoftReference))
   (:refer-clojure :exclude [error-handler]))
 
 (defn stream->str


(def json-handler #(client-handler % error-handler parse-json-body))
(def xml-handler #(client-handler % error-handler parse-xml-body))

  (if (string? body)
    body
    (slurp body)))

(defn soft-reference->json!
  "Given a soft reference object and a Cheshire JSON generator, write the
  data stored in the soft reference to the generator as a JSON string.

  Note, however, that sometimes the value is not a soft reference, but rather
  a raw value from the response. In that case, we need to skip the object
  conversion, and just do the realization."
  [obj json-generator]
  (let [data @(if (isa? obj SoftReference)
                (.get obj)
                obj)
        data-str (json/generate-string data)]
    (log/trace "Encoder got data: " data)
    (.writeString json-generator data-str)))

;; This adds support for JSON-encoding the data cached in a SoftReference.
(json-gen/add-encoder SoftReference soft-reference->json!)

(defn parse-json-body
  [body]
