diff --git a/deps.edn b/deps.edn index 2defffd..163693a 100644 --- a/deps.edn +++ b/deps.edn @@ -17,7 +17,8 @@ :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} less-awful-ssl/less-awful-ssl {:mvn/version "1.0.6"} eftest/eftest {:mvn/version "0.6.0"} - clj-http/clj-http {:mvn/version "3.12.0"}}} + clj-http/clj-http {:mvn/version "3.12.0"} + ring/ring-core {:mvn/version "1.10.0"}}} :project {:extra-deps {io.github.exoscale/tools.project {:git/sha "4ad527fac7bdc24f649404205ca31754339f856d"}} :ns-default exoscale.tools.project diff --git a/src/s_exp/mina/response.clj b/src/s_exp/mina/response.clj index 717bb83..6992fd0 100644 --- a/src/s_exp/mina/response.clj +++ b/src/s_exp/mina/response.clj @@ -7,6 +7,12 @@ (io.helidon.webserver.http ServerResponse) (java.io FileInputStream InputStream OutputStream))) +(def ^:no-doc ring-core-loaded? + (try + (require 'ring.core.protocols) + true + (catch Throwable _ false))) + (defprotocol BodyWriter (write-body! [x server-response])) @@ -37,6 +43,16 @@ (write-body! [o server-response] (.send ^ServerResponse server-response o))) +(when ring-core-loaded? + (extend-protocol BodyWriter + Object + (write-body! [o server-response] + (let [StreamableResponseBody @(ns-resolve 'ring.core.protocols 'StreamableResponseBody) + write-body-to-stream (ns-resolve 'ring.core.protocols 'write-body-to-stream)] + (if (satisfies? StreamableResponseBody o) + (write-body-to-stream o nil (.outputStream server-response)) + (.send ^ServerResponse server-response o)))))) + (defn header-name ^HeaderName [ring-header-name] (HeaderNames/createFromLowercase (name ring-header-name))) @@ -62,4 +78,3 @@ (set-headers! server-response headers) (set-status! server-response status) (write-body! body server-response)) - diff --git a/test/s_exp/mina_test.clj b/test/s_exp/mina_test.clj index 234cbc1..8e1a594 100644 --- a/test/s_exp/mina_test.clj +++ b/test/s_exp/mina_test.clj @@ -3,7 +3,9 @@ [clojure.string :as str] [clojure.test :refer :all] [less.awful.ssl :as ls] - [s-exp.mina :as m]) + [s-exp.mina :as m] + [ring.core.protocols :as p] + [clojure.java.io :as io]) (:import (io.helidon.common.tls Tls TlsClientAuth) (io.helidon.common.tls TlsConfig))) @@ -94,5 +96,19 @@ :trust-store "test/keystore.jks" :trust-store-pass "password"})))))) - - +(deftest test-streamable-body + (with-server {:handler (fn [_req] + {:status 200 + :headers {"content-type" "text/event-stream" + "transfer-encoding" "chunked"} + :body (reify p/StreamableResponseBody + (write-body-to-stream [_ _ output-stream] + (with-open [w (io/writer output-stream)] + (doseq [n (range 1 6)] + (doto w + (.write (str "data: " n "\n\n")) + (.flush))))))})} + (let [resp (client/get *endpoint*)] + (is (status-ok? resp)) + (is (= "data: 1\n\ndata: 2\n\ndata: 3\n\ndata: 4\n\ndata: 5\n\n" + (:body resp))))))