Skip to content

Commit

Permalink
Add support for url encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
bsless committed Aug 24, 2021
1 parent c5e5a60 commit 9080e5c
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 26 deletions.
69 changes: 45 additions & 24 deletions src/contextual/http.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@

(defn ^String url-encode
[s]
(URLEncoder/encode (str s) "utf8"))
(.replace (URLEncoder/encode (str s) "utf8") "+" "%20"))

(comment
(url-encode (url-encode "foo bar")))

(def ^:const path-sep "/")
(def ^:const url-sep ".")
Expand All @@ -28,28 +31,38 @@
))

(defn- emit-scalar
[k]
(cond
(or (keyword? k) (symbol? k)) (name k)
:else k))
([k]
(emit-scalar k false))
([k encode?]
(cond->
(cond
(or (keyword? k) (symbol? k)) (name k)
:else k)
encode? url-encode)))

(defn- emit-kv-pair
[k v]
(when k
(cond
(and (scalar? k) (scalar? v)) (str (emit-scalar k) "=" (emit-scalar v) "&")
(scalar? k) (list 'str (emit-scalar k) "=" v "&")
(some? k) `(~'kv ~k ~v))))
([k v]
(emit-kv-pair k v false))
([k v encode?]
(when k
(cond
(and (scalar? k) (scalar? v)) (str (emit-scalar k encode?) "=" (emit-scalar v encode?) "&")
(scalar? k) (list 'str (emit-scalar k encode?) "=" (if encode? (list 'url-encode v) v) "&")
(some? k) (if encode?
`(~'kv (~'url-encode ~k) (~'url-encode ~v))
`(~'kv ~k ~v))))))

(defn qs->ir
[m]
(let [parts (into
[]
(comp
(map (fn [[k v]] (emit-kv-pair k v)))
compress-string-xf)
m)]
`(~'str ~@(conj parts '__qs-trim))))
([m]
(qs->ir m false))
([m encode?]
(let [parts (into
[]
(comp
(map (fn [[k v]] (emit-kv-pair k v encode?)))
compress-string-xf)
m)]
`(~'str ~@(conj parts '__qs-trim)))))

(comment
(def ir (qs->ir
Expand All @@ -71,11 +84,19 @@
([path]
(path->ir path path-sep))
([path sep]
(path->ir path sep false))
([path sep encode?]
(cond
(string? path) path
(strexpr? path) path
:else (let [path (interpose sep path)
path (transduce compress-string-xf conj [] path)]
:else (let [path (transduce (comp (if encode?
(map (fn [part]
(if (scalar? part)
(emit-scalar part true)
`(~'url-encode ~part))))
identity)
(interpose sep)
compress-string-xf) conj [] path)]
(if (= 1 (count path)) (first path)
(list* 'str path))))))

Expand All @@ -98,8 +119,8 @@
serialize-form]}]
(let [url (cond->
(path->ir url url-sep)
path (as-> $ `(~'str ~$ "/" ~(path->ir path)))
serialize-query-params (as-> $ `(~'str ~$ "?" ~(qs->ir query-params))))
path (as-> $ `(~'str ~$ "/" ~(path->ir path path-sep true)))
serialize-query-params (as-> $ `(~'str ~$ "?" ~(qs->ir query-params serialize-query-params))))
body (when body (if serialize-body (list 'body-serializer body) body))
form (when form (if serialize-form (list 'form-serializer form) form))]
(cond->
Expand Down Expand Up @@ -282,5 +303,5 @@
(when serialize-form {'form-serializer form-serializer}))]
(-compile-request
(request req opts)
lookup
(assoc lookup 'url-encode #'url-encode)
(merge symbols-registry http-symbols-registry registry)))))
40 changes: 38 additions & 2 deletions test/contextual/http_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@

(t/testing "Expression"
(t/is
(= '{:url (str (str "https://" (path :foo) ".bar.com") "/" (path :bar))
(= '{:url (str (str "https://" (path :foo) ".bar.com") "/" (url-encode (path :bar)))
:method "GET"}
(sut/request '{:url (str "https://" (path :foo) ".bar.com")
:path [(path :bar)]}
{}))))

(t/testing "Vector"
(t/is
(= '{:url (str (str "https://hello." (path :foo) ".bar.com") "/" (str "fizz/" (path :buzz)))
(= '{:url (str (str "https://hello." (path :foo) ".bar.com") "/" (str "fizz/" (url-encode (path :buzz))))
:method "GET"}
(sut/request '{:url ["https://hello" (path :foo) "bar.com"]
:path ["fizz" (path :buzz)]}
Expand Down Expand Up @@ -345,3 +345,39 @@
(=
{:method "GET", :url "http://www.query-params-issue.com?ip=127.0.0.1"}
(contextual.core/invoke compiled {:ip "127.0.0.1"})))))

(t/deftest encoding

(t/testing "Path"
(t/is
(= {:url (str "https://bar.com/fi%20zz/hello%20world")
:method "GET"}
(invoke
(sut/compile-request
'{:url (str "https://bar.com")
:path [(path :foo) (path :bar)]}
{})
{:foo "fi zz"
:bar "hello world"}))))

(t/testing "Query params"
(t/testing "Serialized"
(t/is
(= {:url "https://foo.bar.com?a=1&b%20B=B%20b&c=x%20X&d%20D=y%20Y&e%20E=z"
:method "GET"}
(invoke
(sut/compile-request
'{:url "https://foo.bar.com"
:query-params {:a 1
"b B" "B b"
:c (path :x)
(path :d) (path :y)
(path :e) "z"
}}
{}
{}
{:serialize-query-params true})
{:x "x X"
:d "d D"
:y "y Y"
:e "e E"}))))))

0 comments on commit 9080e5c

Please sign in to comment.