From a7b0b508c8ca7614a2deffb3142ea14b522654f7 Mon Sep 17 00:00:00 2001 From: James Reeves Date: Fri, 2 Feb 2024 01:23:02 +0000 Subject: [PATCH] Move ring.core.protocols into its own library Move the ring.core.protocols namespace into its own library, thereby allowing third-party adapters to use the core Ring protocols without needing to depend on all of the ring/ring-core package. Add a dependency on the new org.ring-clojure/ring-core-protocols library to ring/ring-core to maintain backward compatibility. --- .github/workflows/test.yml | 4 +++ ring-core-protocols/project.clj | 9 +++++++ .../src/ring/core/protocols.clj | 26 ++++++++++++++++--- .../test/ring/assets/hello world.txt | 1 + .../test/ring/core/test/protocols.clj | 0 ring-core/project.clj | 1 + 6 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 ring-core-protocols/project.clj rename {ring-core => ring-core-protocols}/src/ring/core/protocols.clj (64%) create mode 100644 ring-core-protocols/test/ring/assets/hello world.txt rename {ring-core => ring-core-protocols}/test/ring/core/test/protocols.clj (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d459cc38..bf70b9630 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,10 @@ jobs: key: cljdeps-${{ hashFiles('project.clj', 'ring-*/project.clj') }} restore-keys: cljdeps- + - name: Install core protocols project locally + run: lein install + working-directory: ./ring-core-protocols + - name: Install websocket protocols project locally run: lein install working-directory: ./ring-websocket-protocols diff --git a/ring-core-protocols/project.clj b/ring-core-protocols/project.clj new file mode 100644 index 000000000..79e2678e0 --- /dev/null +++ b/ring-core-protocols/project.clj @@ -0,0 +1,9 @@ +(defproject org.ring-clojure/ring-core-protocols "1.11.0" + :description "Ring core protocols." + :url "https://github.com/ring-clojure/ring" + :scm {:dir ".."} + :license {:name "The MIT License" + :url "http://opensource.org/licenses/MIT"} + :dependencies [] + :profiles + {:dev {:dependencies [[org.clojure/clojure "1.7.0"]]}}) diff --git a/ring-core/src/ring/core/protocols.clj b/ring-core-protocols/src/ring/core/protocols.clj similarity index 64% rename from ring-core/src/ring/core/protocols.clj rename to ring-core-protocols/src/ring/core/protocols.clj index c3a68ff22..64a73122b 100644 --- a/ring-core/src/ring/core/protocols.clj +++ b/ring-core-protocols/src/ring/core/protocols.clj @@ -2,8 +2,7 @@ "Protocols necessary for Ring." {:added "1.6"} (:import [java.io Writer OutputStream]) - (:require [clojure.java.io :as io] - [ring.util.response :as response])) + (:require [clojure.java.io :as io])) (defprotocol ^{:added "1.6"} StreamableResponseBody "A protocol for writing data to the response body via an output stream." @@ -12,8 +11,27 @@ will be closed after the value had been written. The stream may be written asynchronously.")) -(defn- ^Writer response-writer [response output-stream] - (if-let [charset (response/get-charset response)] +;; The following private functions are replicated from ring.util.response in +;; order to allow third-party adapters to use StreamableResponseBody without the +;; need for a ring-core dependency. + +(def ^:private re-charset + #"(?x);(?:.*\s)?(?i:charset)=(?: + ([!\#$%&'*\-+.0-9A-Z\^_`a-z\|~]+)| # token + \"((?:\\\"|[^\"])*)\" # quoted + )\s*(?:;|$)") + +(defn- find-charset-in-content-type [content-type] + (when-let [m (re-find re-charset content-type)] + (or (m 1) (m 2)))) + +(defn- response-charset [response] + (some->> (:headers response) + (some #(when (.equalsIgnoreCase "content-type" (key %)) (val %))) + (find-charset-in-content-type))) + +(defn- response-writer ^Writer [response output-stream] + (if-let [charset (response-charset response)] (io/writer output-stream :encoding charset) (io/writer output-stream))) diff --git a/ring-core-protocols/test/ring/assets/hello world.txt b/ring-core-protocols/test/ring/assets/hello world.txt new file mode 100644 index 000000000..557db03de --- /dev/null +++ b/ring-core-protocols/test/ring/assets/hello world.txt @@ -0,0 +1 @@ +Hello World diff --git a/ring-core/test/ring/core/test/protocols.clj b/ring-core-protocols/test/ring/core/test/protocols.clj similarity index 100% rename from ring-core/test/ring/core/test/protocols.clj rename to ring-core-protocols/test/ring/core/test/protocols.clj diff --git a/ring-core/project.clj b/ring-core/project.clj index d4a711036..790d4c60d 100644 --- a/ring-core/project.clj +++ b/ring-core/project.clj @@ -5,6 +5,7 @@ :license {:name "The MIT License" :url "http://opensource.org/licenses/MIT"} :dependencies [[org.clojure/clojure "1.7.0"] + [org.ring-clojure/ring-core-protocols "1.11.0"] [org.ring-clojure/ring-websocket-protocols "1.11.0"] [ring/ring-codec "1.2.0"] [commons-io "2.15.0"]