[Git][clojure-team/ring-codec-clojure][upstream] New upstream version 1.3.0

Thomas Goirand (@zigo) gitlab at salsa.debian.org
Mon Jul 20 21:46:49 BST 2026



Thomas Goirand pushed to branch upstream at Debian Clojure Maintainers / ring-codec-clojure


Commits:
b441bcd2 by Thomas Goirand at 2026-07-20T22:39:44+02:00
New upstream version 1.3.0
- - - - -


7 changed files:

- + .github/workflows/test.yml
- .gitignore
- − .travis.yml
- README.md
- project.clj
- src/ring/util/codec.clj
- test/ring/util/test/codec.clj


Changes:

=====================================
.github/workflows/test.yml
=====================================
@@ -0,0 +1,29 @@
+name: Tests
+on: [push, pull_request]
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout at v3
+
+      - name: Prepare java
+        uses: actions/setup-java at v3
+        with:
+          distribution: 'zulu'
+          java-version: '11'
+
+      - name: Install clojure tools
+        uses: DeLaGuardo/setup-clojure at 10.1
+        with:
+          lein: 2.9.10
+
+      - name: Cache clojure dependencies
+        uses: actions/cache at v3
+        with:
+          path: ~/.m2/repository
+          key: cljdeps-${{ hashFiles('project.clj') }}
+          restore-keys: cljdeps-
+
+      - name: Run tests
+        run: lein test-all


=====================================
.gitignore
=====================================
@@ -11,3 +11,5 @@ pom.xml.asc
 .lein-failures
 .lein-plugins
 .lein-repl-history
+/.clj-kondo
+/.cpcache


=====================================
.travis.yml deleted
=====================================
@@ -1,2 +0,0 @@
-language: clojure
-script: lein test-all


=====================================
README.md
=====================================
@@ -1,15 +1,17 @@
-# Ring-Codec
-
-[![Build Status](https://travis-ci.org/ring-clojure/ring-codec.svg?branch=master)](https://travis-ci.org/ring-clojure/ring-codec)
+# Ring-Codec [![Build Status](https://github.com/ring-clojure/ring-codec/actions/workflows/test.yml/badge.svg)](https://github.com/ring-clojure/ring-codec/actions/workflows/test.yml)
 
 Functions for encoding and decoding data into formats commonly used in
 web applications.
 
 ## Installation
 
-To install, add the following to your project `:dependencies`:
+Add the following dependency to your deps.edn file:
+
+    ring/ring-codec {:mvn/version "1.3.0"}
+
+Or to your Leiningen project file:
 
-    [ring/ring-codec "1.2.0"]
+    [ring/ring-codec "1.3.0"]
 
 ## Documentation
 
@@ -17,6 +19,6 @@ To install, add the following to your project `:dependencies`:
 
 ## License
 
-Copyright © 2021 James Reeves
+Copyright © 2025 James Reeves
 
 Distributed under the MIT License, the same as Ring.


=====================================
project.clj
=====================================
@@ -1,16 +1,16 @@
-(defproject ring/ring-codec "1.2.0"
+(defproject ring/ring-codec "1.3.0"
   :description "Library for encoding and decoding data"
   :url "https://github.com/ring-clojure/ring-codec"
   :license {:name "The MIT License"
             :url "http://opensource.org/licenses/MIT"}
-  :dependencies [[org.clojure/clojure "1.7.0"]]
-  :plugins [[lein-codox "0.10.7"]]
+  :dependencies [[org.clojure/clojure "1.9.0"]]
+  :plugins [[lein-codox "0.10.8"]]
   :codox
   {:output-path "codox"
    :source-uri "http://github.com/ring-clojure/ring-codec/blob/{version}/{filepath}#L{line}"}
-  :aliases {"test-all" ["with-profile" "default:+1.8:+1.9:+1.10" "test"]}
+  :aliases {"test-all" ["with-profile" "default:+1.10:+1.11:+1.12" "test"]}
   :profiles
   {:dev  {:dependencies [[criterium "0.4.6"]]}
-   :1.8  {:dependencies [[org.clojure/clojure "1.8.0"]]}
-   :1.9  {:dependencies [[org.clojure/clojure "1.9.0"]]}
-   :1.10 {:dependencies [[org.clojure/clojure "1.10.3"]]}})
+   :1.10 {:dependencies [[org.clojure/clojure "1.10.3"]]}
+   :1.11 {:dependencies [[org.clojure/clojure "1.11.4"]]}
+   :1.12 {:dependencies [[org.clojure/clojure "1.12.0"]]}})


=====================================
src/ring/util/codec.clj
=====================================
@@ -3,6 +3,7 @@
   (:require [clojure.string :as str])
   (:import java.util.Map
            clojure.lang.MapEntry
+           java.nio.charset.Charset
            [java.net URLEncoder URLDecoder]
            [java.util Base64 StringTokenizer]))
 
@@ -28,53 +29,65 @@
     `(double-escape ~x)
     x))
 
+(def ^:private ^Charset utf-8 (Charset/forName "UTF-8"))
+
+(defn- ^Charset to-charset [s]
+  (if (nil? s) utf-8 (if (string? s) (Charset/forName s) s)))
+
 (defn percent-encode
   "Percent-encode every character in the given string using either the specified
   encoding, or UTF-8 by default."
   ([unencoded]
-   (percent-encode unencoded "UTF-8"))
-  ([^String unencoded ^String encoding]
-   (->> (.getBytes unencoded encoding)
+   (percent-encode unencoded utf-8))
+  ([^String unencoded encoding]
+   (->> (.getBytes unencoded (to-charset encoding))
         (map (partial format "%%%02X"))
         (str/join))))
 
-(defn- parse-bytes [encoded-bytes]
-  (->> (re-seq #"%[A-Za-z0-9]{2}" encoded-bytes)
-       (map #(subs % 1))
-       (map #(.byteValue (Integer/valueOf % 16)))
-       (byte-array)))
+(defn- parse-bytes ^bytes [encoded-bytes]
+  (let [encoded-len (count encoded-bytes)
+        bs (byte-array (/ encoded-len 3))]
+    (loop [encoded-index 1, byte-index 0]
+      (if (< encoded-index encoded-len)
+        (let [encoded-byte (subs encoded-bytes encoded-index (+ encoded-index 2))
+              b (.byteValue (Integer/valueOf encoded-byte 16))]
+          (aset bs byte-index b)
+          (recur (+ encoded-index 3) (inc byte-index)))
+        bs))))
 
 (defn percent-decode
   "Decode every percent-encoded character in the given string using the
   specified encoding, or UTF-8 by default."
   ([encoded]
-   (percent-decode encoded "UTF-8"))
-  ([^String encoded ^String encoding]
-   (str/replace encoded
-                #"(?:%[A-Za-z0-9]{2})+"
-                (fn [chars]
-                  (-> ^bytes (parse-bytes chars)
-                      (String. encoding)
-                      (fix-string-replace-bug))))))
+   (percent-decode encoded utf-8))
+  ([^String encoded encoding]
+   (let [encoding (to-charset encoding)]
+     (str/replace encoded
+                  #"(?:%[A-Fa-f0-9]{2})+"
+                  (fn [chars]
+                    (-> (parse-bytes chars)
+                        (String. encoding)
+                        (fix-string-replace-bug)))))))
 
 (defn url-encode
   "Returns the url-encoded version of the given string, using either a specified
   encoding or UTF-8 by default."
   ([unencoded]
-   (url-encode unencoded "UTF-8"))
+   (url-encode unencoded utf-8))
   ([unencoded encoding]
-   (str/replace
-    unencoded
-    #"[^A-Za-z0-9_~.+-]+"
-    #(double-escape (percent-encode % encoding)))))
+   (let [encoding (to-charset encoding)]
+     (str/replace
+      unencoded
+      #"[^A-Za-z0-9_~.+-]+"
+      #(double-escape (percent-encode % encoding))))))
 
 (defn ^String url-decode
   "Returns the url-decoded version of the given string, using either a specified
   encoding or UTF-8 by default. If the encoding is invalid, nil is returned."
   ([encoded]
-   (url-decode encoded "UTF-8"))
+   (url-decode encoded utf-8))
   ([encoded encoding]
-   (percent-decode encoded encoding)))
+   (percent-decode encoded (to-charset encoding))))
 
 (defn base64-encode
   "Encode an array of bytes into a base64 encoded string."
@@ -92,7 +105,7 @@
 (extend-protocol FormEncodeable
   String
   (form-encode* [^String unencoded ^String encoding]
-    (URLEncoder/encode unencoded encoding))
+    (URLEncoder/encode unencoded (to-charset encoding)))
   Map
   (form-encode* [params encoding]
     (letfn [(encode [x] (form-encode* x encoding))
@@ -116,19 +129,24 @@
   URL query strings and POST request bodies, using the specified encoding.
   If the encoding is not specified, it defaults to UTF-8"
   ([x]
-   (form-encode x "UTF-8"))
+   (form-encode x utf-8))
   ([x encoding]
    (form-encode* x encoding)))
 
+(defn- form-encoded-chars? [^String s]
+  (or (.contains s "+") (.contains s "%")))
+
 (defn form-decode-str
   "Decode the supplied www-form-urlencoded string using the specified encoding,
   or UTF-8 by default."
   ([encoded]
-   (form-decode-str encoded "UTF-8"))
-  ([^String encoded ^String encoding]
-   (try
-     (URLDecoder/decode encoded ^String (or encoding "UTF-8"))
-     (catch Exception _ nil))))
+   (form-decode-str encoded utf-8))
+  ([^String encoded encoding]
+   (if (form-encoded-chars? encoded)
+     (try
+       (URLDecoder/decode encoded (to-charset encoding))
+       (catch Exception _ nil))
+     encoded)))
 
 (defn- tokenized [s delim]
   (reify clojure.lang.IReduceInit
@@ -139,29 +157,40 @@
             (recur (f result (.nextToken tokenizer)))
             result))))))
 
+(def ^:private ^:const kv-separator (int \=))
+
 (defn- split-key-value-pair [^String s]
-  (let [i (.indexOf s #=(int \=))]
+  (let [i (.indexOf s kv-separator)]
     (cond
       (pos? i)  (MapEntry. (.substring s 0 i) (.substring s (inc i)))
       (zero? i) (MapEntry. "" (.substring s (inc i)))
       :else     (MapEntry. s ""))))
 
+(defn form-decode-map
+  "Decode the supplied www-form-urlencoded string using the specified encoding,
+  or UTF-8 by default. Expects an encoded map of key/value pairs as defined by:
+  https://url.spec.whatwg.org/#urlencoded-parsing"
+  ([encoded]
+   (form-decode-map encoded utf-8))
+  ([^String encoded encoding]
+   (reduce
+    (fn [m param]
+      (let [kv (split-key-value-pair param)
+            k  (form-decode-str (key kv) encoding)
+            v  (form-decode-str (val kv) encoding)]
+        (if (and k v)
+          (assoc-conj m k v)
+          m)))
+    {}
+    (tokenized encoded "&"))))
+
 (defn form-decode
   "Decode the supplied www-form-urlencoded string using the specified encoding,
   or UTF-8 by default. If the encoded value is a string, a string is returned.
   If the encoded value is a map of parameters, a map is returned."
   ([encoded]
-   (form-decode encoded "UTF-8"))
+   (form-decode encoded utf-8))
   ([^String encoded encoding]
    (if-not (.contains encoded "=")
      (form-decode-str encoded encoding)
-     (reduce
-      (fn [m param]
-        (let [kv (split-key-value-pair param)
-              k  (form-decode-str (key kv) encoding)
-              v  (form-decode-str (val kv) encoding)]
-          (if (and k v)
-            (assoc-conj m k v)
-            m)))
-      {}
-      (tokenized encoded "&")))))
+     (form-decode-map encoded encoding))))


=====================================
test/ring/util/test/codec.clj
=====================================
@@ -1,7 +1,8 @@
 (ns ring.util.test.codec
   (:use clojure.test
         ring.util.codec)
-  (:import java.util.Arrays))
+  (:import java.util.Arrays
+           java.nio.charset.Charset))
 
 (deftest test-percent-encode
   (is (= (percent-encode " ") "%20"))
@@ -9,7 +10,7 @@
   (is (= (percent-encode "foo") "%66%6F%6F")))
 
 (deftest test-percent-decode
-  (is (= (percent-decode "%s/") "%s/"))
+  (is (= (percent-decode "%s4/") "%s4/"))
   (is (= (percent-decode "%20") " "))
   (is (= (percent-decode "foo%20bar") "foo bar"))
   (is (= (percent-decode "foo%FE%FF%00%2Fbar" "UTF-16") "foo/bar"))
@@ -17,7 +18,10 @@
 
 (deftest test-url-encode
   (is (= (url-encode "foo/bar") "foo%2Fbar"))
+  (is (= (url-encode "foo/bar" nil) "foo%2Fbar"))
+  (is (= (url-encode "foo/bar" "UTF-8") "foo%2Fbar"))
   (is (= (url-encode "foo/bar" "UTF-16") "foo%FE%FF%00%2Fbar"))
+  (is (= (url-encode "foo/bar" (Charset/forName "UTF-16")) "foo%FE%FF%00%2Fbar"))
   (is (= (url-encode "foo+bar") "foo+bar"))
   (is (= (url-encode "foo bar") "foo%20bar")))
 
@@ -57,6 +61,30 @@
   (is (= (form-decode-str "foo=bar+baz" nil) "foo=bar baz"))
   (is (= (form-decode-str "foo=bar+baz" "UTF-8") "foo=bar baz")))
 
+(deftest test-form-decode-map
+  (are [x y] (= (form-decode-map x) y)
+    "foo"     {"foo" ""}
+    "a=b"     {"a" "b"}
+    "a=b&c=d" {"a" "b" "c" "d"}
+    "foo+bar" {"foo bar" ""}
+    "a=b+c"   {"a" "b c"}
+    "a=b%2Fc" {"a" "b/c"}
+    "a=b&c"   {"a" "b" "c" ""}
+    "a=&b=c"  {"a" "" "b" "c"}
+    "a&b=c"   {"a" "" "b" "c"}
+    "="       {"" ""}
+    "a="      {"a" ""}
+    "=b"      {"" "b"})
+  (testing "invalid URL encoding"
+    (are [x y] (= (form-decode-map x) y)
+      "%=b" {}
+      "a=%" {}
+      "%=%" {}))
+  (is (= (form-decode-map "a=foo%FE%FF%00%2Fbar" "UTF-16")
+         {"a" "foo/bar"}))
+  (is (= (form-decode-map "a=foo%2Fbar" nil)
+         {"a" "foo/bar"})))
+
 (deftest test-form-decode
   (are [x y] (= (form-decode x) y)
     "foo"     "foo"



View it on GitLab: https://salsa.debian.org/clojure-team/ring-codec-clojure/-/commit/b441bcd20ceec3c803cf43d64f7783a9e19f1219

-- 
View it on GitLab: https://salsa.debian.org/clojure-team/ring-codec-clojure/-/commit/b441bcd20ceec3c803cf43d64f7783a9e19f1219
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20260720/60d373c4/attachment.htm>


More information about the pkg-java-commits mailing list