Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Protocol for form-encode to support strings and maps

  • Loading branch information...
commit 053832d737dd5150a1b5a183be8f7e4c26a36222 1 parent 98bb0b9
@weavejester weavejester authored
View
50 ring-core/src/ring/util/codec.clj
@@ -3,6 +3,7 @@
(:use ring.util.data)
(:require [clojure.string :as str])
(:import java.io.File
+ java.util.Map
(java.net URLEncoder URLDecoder)
org.apache.commons.codec.binary.Base64))
@@ -59,6 +60,35 @@
[^String encoded]
(Base64/decodeBase64 (.getBytes encoded)))
+(defprotocol FormEncodeable
+ (form-encode* [x encoding]))
+
+(defn form-encode
+ "Encode the supplied value into www-form-urlencoded format, often used in
+ URL query strings and POST request bodies, using the specified encoding.
+ If the encoding is not specified, it defaults to UTF-8"
+ [x & [encoding]]
+ (form-encode* x (or encoding "UTF-8")))
+
+(extend-protocol FormEncodeable
+ String
+ (form-encode* [unencoded encoding]
+ (URLEncoder/encode unencoded encoding))
+ Map
+ (form-encode* [params encoding]
+ (letfn [(encode [x] (form-encode x encoding))
+ (encode-param [[k v]] (str (encode (name k)) "=" (encode v)))]
+ (->> params
+ (mapcat
+ (fn [[k v]]
+ (if (or (seq? v) (sequential? v) )
+ (map #(encode-param [k %]) v)
+ [(encode-param [k v])])))
+ (str/join "&"))))
+ Object
+ (form-encode* [x encoding]
+ (form-encode* (str x) encoding)))
+
(defn form-decode
"Parse parameters from a string into a map."
([^String param-string]
@@ -73,23 +103,3 @@
param-map))
{}
(str/split param-string #"&"))))
-
-(defn form-encode
- "Encode parameters from a map into a string."
- ([param-map]
- (form-encode param-map "UTF-8"))
- ([param-map encoding]
- (form-encode (keys param-map)
- (vals param-map)
- encoding))
- ([params values encoding]
- (str/join #"&"
- (map (fn [param value]
- (if (vector? value)
- (form-encode (repeat (count value) param)
- value
- encoding)
- (str (url-encode param)
- "="
- (url-encode value))))
- params values))))
View
16 ring-core/test/ring/util/test/codec.clj
@@ -28,6 +28,22 @@
(let [str-bytes (.getBytes "foo?/+" "UTF-8")]
(is (Arrays/equals str-bytes (base64-decode (base64-encode str-bytes))))))
+(deftest test-form-encode
+ (testing "strings"
+ (are [x y] (= (form-encode x) y)
+ "foo bar" "foo+bar"
+ "foo+bar" "foo%2Bbar"
+ "foo/bar" "foo%2Fbar")
+ (is (= (form-encode "foo/bar" "UTF-16") "foo%FE%FF%00%2Fbar")))
+ (testing "maps"
+ (are [x y] (= (form-encode x) y)
+ {"a" "b"} "a=b"
+ {:a "b"} "a=b"
+ {"a" 1} "a=1"
+ {"a" "b" "c" "d"} "a=b&c=d"
+ {"a" "b c"} "a=b+c")
+ (is (= (form-encode {"a" "foo/bar"} "UTF-16") "a=foo%FE%FF%00%2Fbar"))))
+
(deftest form-encoding
(let [encoded-params "p%2F1=v%2F1&p%2F2=v%2F21&p%2F2=v%2F22"]
(is (= (form-decode encoded-params)
Please sign in to comment.
Something went wrong with that request. Please try again.