Skip to content

Commit 02279a8

Browse files
authored
Flatten nested query and form parameter maps (#44)
Brought over flattening code from clj-http but not the options to enable/disable flattening. For us, for now, it is always enabled. See updates to README for examples. Closes #43
1 parent 3f5addf commit 02279a8

File tree

4 files changed

+82
-9
lines changed

4 files changed

+82
-9
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
- If specified, request's body encoding is now applied, else defaults to UTF-8 ([#18](https://github.com/clj-commons/clj-http-lite/issues/18)) ([@lread](https://github.com/lread))
44
- User info from request URL now applied to basic auth ([#34](https://github.com/clj-commons/clj-http-lite/issues/34)) ([@lread](https://github.com/lread))
5+
- Nested query and form parameters are now automatically flattened ([#43](https://github.com/clj-commons/clj-http-lite/issues/43)) ([@lread](https://github.com/lread))
56
- Quality
7+
- Docstrings reviewed and updated
68
- Automated CI testing added for Windows ([#21](https://github.com/clj-commons/clj-http-lite/issues/21)) ([@lread](https://github.com/lread))
79

810
### 0.4.384

README.md

+39-8
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ A Clojure HTTP library similar to [clj-http](http://github.com/dakrone/clj-http)
1818

1919
- Instead of Apache HttpClient, clj-http-lite uses HttpURLConnection
2020
- No automatic JSON decoding for response bodies
21+
- No automatic request body encoding beyond charset and url encoding of form params
2122
- No cookie support
2223
- No multipart form uploads
2324
- No persistent connection support
25+
- Fewer options
2426
- namespace rename clj-http.* -> clj-http.lite.*
2527

28+
Like its namesake, clj-http-lite is light and simple, but ping us if there is some clj-http feature you'd like to see in clj-http-lite. We can discuss.
2629
## History
2730

2831
- Sep 2011 - [dakrone/clj-http](https://github.com/dakrone/clj-http) created (and is still actively maintained)
@@ -92,6 +95,41 @@ codes.
9295
The client transparently accepts and decompresses the `gzip` and
9396
`deflate` content encodings.
9497

98+
### Nested params
99+
100+
Nested parameter `{:a {:b 1}}` in `:form-params` or `:query-params` is automatically flattened to `a[b]=1`.
101+
We'll use `httpbin.org` to demonstrate:
102+
103+
```clojure
104+
(-> (client/get "https://httpbin.org/get"
105+
{:query-params {:one {:two 2 :three 3}}})
106+
:body
107+
println)
108+
{
109+
"args": {
110+
"one[three]": "3",
111+
"one[two]": "2"
112+
},
113+
...
114+
}
115+
116+
(-> (client/post "https://httpbin.org/post"
117+
{:form-params {:one {:two 2
118+
:three {:four {:five 5}}}
119+
:six 6}})
120+
:body
121+
println)
122+
{
123+
...
124+
"form": {
125+
"one[three][four][five]": "5",
126+
"one[two]": "2",
127+
"six": "6"
128+
},
129+
...
130+
}
131+
```
132+
95133
### Input coercion
96134

97135
```clojure
@@ -188,18 +226,11 @@ such), check out the
188226

189227
## Known Issues
190228

191-
- Nested form params [aren't serialized correctly](https://github.com/hiredman/clj-http-lite/issues/15). There's an easy workaround however:
192-
193-
```clojure
194-
:form-params {"toplevel" {"nested" some-data}} ; doesn't work
195-
:form-params {"toplevel[nested]" some-data} ; works
196-
```
197-
198229
- If you issue HTTPS connections, [Native Image](https://www.graalvm.org/docs/reference-manual/native-image/) compilation requires an additional parameter in order to enable its support in the generated image.
199230

200231
If you get the following kind of error:
201232

202-
Exception in thread "main" java.net.MalformedURLException: Accessing an URL protocol that was not enabled.
233+
Exception in thread "main" java.net.MalformedURLException: Accessing an URL protocol that was not enabled.
203234
The URL protocol https is supported but not enabled by default. It must be enabled by adding the
204235
-H:EnableURLProtocols=https option to the native-image command.
205236

src/clj_http/lite/client.clj

+24-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
[clj-http.lite.links :refer [wrap-links]]
88
[clj-http.lite.util :as util]
99
[clojure.java.io :as io]
10-
[clojure.string :as str])
10+
[clojure.string :as str]
11+
[clojure.walk :as walk])
1112
(:import (java.net UnknownHostException)
1213
(java.nio.charset Charset))
1314
(:refer-clojure :exclude (get update)))
@@ -212,6 +213,27 @@
212213
:body (generate-query-string form-params))))
213214
(client req))))
214215

216+
(defn- nest-params
217+
[req param-key]
218+
(if-let [params (req param-key)]
219+
(let [nested (walk/prewalk
220+
#(if (and (vector? %) (map? (second %)))
221+
(let [[fk m] %]
222+
(reduce
223+
(fn [m [sk v]]
224+
(assoc m (str (name fk)
225+
\[ (name sk) \]) v))
226+
{}
227+
m))
228+
%)
229+
params)]
230+
(assoc req param-key nested))
231+
req))
232+
233+
(defn wrap-nested-params [client]
234+
(fn [req]
235+
(client (-> req (nest-params :form-params) (nest-params :query-params)))))
236+
215237
(defn wrap-url [client]
216238
(fn [req]
217239
(if-let [url (:url req)]
@@ -255,6 +277,7 @@
255277
wrap-accept-encoding
256278
wrap-content-type
257279
wrap-form-params
280+
wrap-nested-params
258281
wrap-method
259282
wrap-links
260283
wrap-unknown-host))

test/clj_http/test/client_test.clj

+17
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,23 @@
299299
(is (= "untouched" (:body resp)))
300300
(is (not (contains? resp :content-type))))))
301301

302+
(deftest apply-on-nest-params
303+
(let [param-client (client/wrap-nested-params identity)
304+
params {:a
305+
{:b
306+
{:c 5}
307+
:e
308+
{:f 6}}
309+
:g 7}
310+
resp (param-client {:form-params params :query-params params})]
311+
(is (= {"a[b][c]" 5 "a[e][f]" 6 :g 7} (:form-params resp) (:query-params resp)))))
312+
313+
(deftest pass-on-no-nest-params
314+
(let [m-client (client/wrap-nested-params identity)
315+
in {:key :val}
316+
out (m-client in)]
317+
(is (= out in))))
318+
302319
(deftest t-ignore-unknown-host
303320
(is (thrown? UnknownHostException (client/get "http://aorecuf892983a.com")))
304321
(is (nil? (client/get "http://aorecuf892983a.com"

0 commit comments

Comments
 (0)