Skip to content
This repository has been archived by the owner on Aug 24, 2022. It is now read-only.

Pass full options down to content handlers #54

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 17 additions & 17 deletions src/ring/middleware/format_params.clj
Expand Up @@ -132,19 +132,19 @@
(defn wrap-json-params
"Handles body params in JSON format. See [[wrap-format-params]] for details."
[handler & args]
(let [{:keys [predicate decoder options] :as opts} (impl/extract-options args)]
(let [{:keys [predicate decoder decoder-options] :as opts} (impl/extract-options args)]
(wrap-format-params handler (assoc opts
:predicate (or predicate json-request?)
:decoder (or decoder (make-json-decoder options))))))
:decoder (or decoder (make-json-decoder decoder-options))))))

(defn wrap-json-kw-params
"Handles body params in JSON format. Parses map keys as keywords.
See [[wrap-format-params]] for details."
[handler & args]
(let [{:keys [predicate decoder options] :as opts} (impl/extract-options args)]
(let [{:keys [predicate decoder decoder-options] :as opts} (impl/extract-options args)]
(wrap-format-params handler (assoc opts
:predicate (or predicate json-request?)
:decoder (or decoder (make-json-decoder (assoc options :key-fn true)))))))
:decoder (or decoder (make-json-decoder (assoc decoder-options :key-fn true)))))))

(def ^:no-doc msgpack-request?
(make-type-request-pred #"^application/(vnd.+)?(x-)?msgpack"))
Expand Down Expand Up @@ -223,29 +223,29 @@
(make-type-request-pred #"^application/(vnd.+)?(x-)?transit\+json"))

(defn wrap-transit-json-params
"Handles body params in transit format over **JSON**. You can use an *:options* key to pass
"Handles body params in transit format over **JSON**. You can use an *:decoder-options* key to pass
a map with *:handlers* and *:default-handler* to transit-clj. See [[wrap-format-params]]
for details."
[handler & args]
(let [{:keys [predicate decoder binary? options] :as options} (impl/extract-options args)]
(let [{:keys [predicate decoder binary? decoder-options] :as opts} (impl/extract-options args)]
(wrap-format-params handler
(assoc options
(assoc opts
:predicate (or predicate transit-json-request?)
:decoder (or decoder (make-transit-decoder :json options))
:decoder (or decoder (make-transit-decoder :json decoder-options))
:binary? (if (nil? binary?) true binary?)))))

(def ^:no-doc transit-msgpack-request?
(make-type-request-pred #"^application/(vnd.+)?(x-)?transit\+msgpack"))

(defn wrap-transit-msgpack-params
"Handles body params in transit format over **msgpack**. You can use an *:options* key to pass
"Handles body params in transit format over **msgpack**. You can use an *:decoder-options* key to pass
a map with *:handlers* and *:default-handler* to transit-clj. See [[wrap-format-params]] for details."
[handler & args]
(let [{:keys [predicate decoder binary? options] :as options} (impl/extract-options args)]
(let [{:keys [predicate decoder binary? decoder-options] :as opts} (impl/extract-options args)]
(wrap-format-params handler
(assoc options
(assoc opts
:predicate (or predicate transit-msgpack-request?)
:decoder (or decoder (make-transit-decoder :msgpack options))
:decoder (or decoder (make-transit-decoder :msgpack decoder-options))
:binary? (if (nil? binary?) true binary?)))))

(def ^:no-doc format-wrappers
Expand All @@ -266,15 +266,15 @@
a solid basis for a RESTful API. It will deserialize to *JSON*, *YAML*, *Transit*
or *Clojure* depending on Content-Type header. See [[wrap-format-params]] for
more details.
Options to specific format decoders can be passed in using *:format-options*
option. If should be map of format keyword to options map."
Options to specific format can be passed in using *:format-options* option.
It should be map of format keyword to options map."
[handler & args]
(let [{:keys [formats format-options] :as options} (impl/extract-options args)
common-options (dissoc options :formats :format-options)]
(reduce (fn [h format]
(if-let [wrapper (if
(fn? format) format
(if-let [wrapper (if (fn? format)
format
(format-wrappers (keyword format)))]
(wrapper h (assoc common-options :options (get format-options format)))
(wrapper h (merge common-options (get format-options format)))
h))
handler (or formats default-formats))))
33 changes: 28 additions & 5 deletions test/ring/middleware/format_params_test.clj
Expand Up @@ -46,13 +46,20 @@
(defn key-fn [s]
(-> s (string/replace #"_" "-") keyword))

(defn custom-json-decoder [_]
{:result "decoded with custom decoder"})

(deftest json-options-test
(is (= {:foo-bar "bar"}
(:body-params ((wrap-json-params identity {:options {:key-fn key-fn}})
(:body-params ((wrap-json-params identity {:decoder-options {:key-fn key-fn}})
{:content-type "application/json"
:body (stream "{\"foo_bar\":\"bar\"}")}))))
(is (= {:foo-bar "bar"}
(:body-params ((wrap-restful-params identity {:format-options {:json {:key-fn key-fn}}})
(:body-params ((wrap-restful-params identity {:format-options {:json {:decoder-options {:key-fn key-fn}}}})
{:content-type "application/json"
:body (stream "{\"foo_bar\":\"bar\"}")}))))
(is (= {:result "decoded with custom decoder"}
(:body-params ((wrap-restful-params identity {:format-options {:json {:decoder custom-json-decoder}}})
{:content-type "application/json"
:body (stream "{\"foo_bar\":\"bar\"}")})))))

Expand Down Expand Up @@ -226,14 +233,22 @@

(defrecord Point [x y])

(def readers
(def custom-handlers
{"Point" (transit/read-handler (fn [[x y]] (Point. x y)))})

(defn custom-transit-decoder
[in]
(let [reader (transit/reader in :json {:handlers custom-handlers})]
(transit/read reader)))

(def custom-transit-json-echo
(wrap-transit-json-params identity :options {:handlers readers}))
(wrap-transit-json-params identity :decoder-options {:handlers custom-handlers}))

(def custom-restful-transit-json-echo
(wrap-restful-params identity :format-options {:transit-json {:handlers readers}}))
(wrap-restful-params identity :format-options {:transit-json {:decoder-options {:handlers custom-handlers}}}))

(def custom-decoder-restful-transit-json-echo
(wrap-restful-params identity :format-options {:transit-json {:decoder custom-transit-decoder}}))

(def transit-body "[\"^ \", \"~:p\", [\"~#Point\",[1,2]]]")

Expand All @@ -244,9 +259,17 @@
(is (= {:p (Point. 1 2)}
(:params parsed-req)
(:body-params parsed-req)))))

(testing "wrap-restful-params, transit options"
(let [req (custom-restful-transit-json-echo {:content-type "application/transit+json"
:body (stream transit-body)})]
(is (= {:p (Point. 1 2)}
(:params req)
(:body-params req)))))

(testing "wrap-restful-params, custom decoder"
(let [req (custom-decoder-restful-transit-json-echo {:content-type "application/transit+json"
:body (stream transit-body)})]
(is (= {:p (Point. 1 2)}
(:params req)
(:body-params req))))))