From 14b5c5e9c996cb934e0a3378e8b3cc94a645d0d8 Mon Sep 17 00:00:00 2001 From: Max Penet Date: Sat, 7 Oct 2023 23:03:08 +0200 Subject: [PATCH] websockets init --- deps.edn | 1 + src/s_exp/mina.clj | 7 ++-- src/s_exp/mina/{ => http}/handler.clj | 12 +++---- src/s_exp/mina/{ => http}/request.clj | 2 +- src/s_exp/mina/{ => http}/response.clj | 6 ++-- src/s_exp/mina/websocket/handler.clj | 49 ++++++++++++++++++++++++++ test/s_exp/mina_test.clj | 34 +++++++++--------- 7 files changed, 80 insertions(+), 31 deletions(-) rename src/s_exp/mina/{ => http}/handler.clj (75%) rename src/s_exp/mina/{ => http}/request.clj (99%) rename src/s_exp/mina/{ => http}/response.clj (93%) create mode 100644 src/s_exp/mina/websocket/handler.clj diff --git a/deps.edn b/deps.edn index 2defffd..71aab18 100644 --- a/deps.edn +++ b/deps.edn @@ -10,6 +10,7 @@ com.github.strojure/zmap {:mvn/version "1.3.26"} io.helidon.http/helidon-http {:mvn/version "4.0.0-RC1"} io.helidon.webserver/helidon-webserver {:mvn/version "4.0.0-RC1"} + io.helidon.webserver/helidon-webserver-websocket {:mvn/version "4.0.0-RC1"} io.helidon.webserver/helidon-webserver-http2 {:mvn/version "4.0.0-RC1"}} :aliases diff --git a/src/s_exp/mina.clj b/src/s_exp/mina.clj index 1053ab1..39cb1a9 100644 --- a/src/s_exp/mina.clj +++ b/src/s_exp/mina.clj @@ -1,6 +1,7 @@ (ns s-exp.mina - (:require [s-exp.mina.handler] - [s-exp.mina.options :as options]) + (:require [s-exp.mina.http.handler] + [s-exp.mina.options :as options] + [s-exp.mina.websocket.handler]) (:import (io.helidon.webserver WebServer WebServerConfig WebServerConfig$Builder))) (set! *warn-on-reflection* true) @@ -28,7 +29,7 @@ * `:tls` - a `io.helidon.nima.common.tls.Tls` instance" ([handler options] - (start! (assoc options :handler handler))) + (start! (assoc options :http-handler handler))) ([options] (-> (server-builder (merge default-options options)) .build diff --git a/src/s_exp/mina/handler.clj b/src/s_exp/mina/http/handler.clj similarity index 75% rename from src/s_exp/mina/handler.clj rename to src/s_exp/mina/http/handler.clj index 0b0253d..f5adcf7 100644 --- a/src/s_exp/mina/handler.clj +++ b/src/s_exp/mina/http/handler.clj @@ -1,7 +1,7 @@ -(ns s-exp.mina.handler - (:require [s-exp.mina.options :as options] - [s-exp.mina.request :as request] - [s-exp.mina.response :as response]) +(ns s-exp.mina.http.handler + (:require [s-exp.mina.http.request :as request] + [s-exp.mina.http.response :as response] + [s-exp.mina.options :as options]) (:import (io.helidon.webserver WebServerConfig$Builder) (io.helidon.webserver.http Handler HttpRouting))) @@ -15,7 +15,7 @@ (.build (doto (HttpRouting/builder) (.any - ^"[Lio.helidon.webserver.http.Handler;" + ^"[Lio.helidon.webserver.http.Handler;" (into-array Handler [(reify Handler (handle [_ server-request server-response] @@ -23,6 +23,6 @@ handler (response/set-response! server-response))))]))))))) -(defmethod options/set-server-option! :handler +(defmethod options/set-server-option! :http.handler [^WebServerConfig$Builder builder _ handler options] (set-ring1-handler! builder handler options)) diff --git a/src/s_exp/mina/request.clj b/src/s_exp/mina/http/request.clj similarity index 99% rename from src/s_exp/mina/request.clj rename to src/s_exp/mina/http/request.clj index 7a481e1..352da76 100644 --- a/src/s_exp/mina/request.clj +++ b/src/s_exp/mina/http/request.clj @@ -1,4 +1,4 @@ -(ns s-exp.mina.request +(ns s-exp.mina.http.request (:require [clojure.string :as str] [strojure.zmap.core :as zmap]) (:import (clojure.lang diff --git a/src/s_exp/mina/response.clj b/src/s_exp/mina/http/response.clj similarity index 93% rename from src/s_exp/mina/response.clj rename to src/s_exp/mina/http/response.clj index 717bb83..b37aef4 100644 --- a/src/s_exp/mina/response.clj +++ b/src/s_exp/mina/http/response.clj @@ -1,7 +1,5 @@ -(ns s-exp.mina.response - (:import (io.helidon.http Header - Headers - HeaderNames +(ns s-exp.mina.http.response + (:import (io.helidon.http HeaderNames HeaderName Status) (io.helidon.webserver.http ServerResponse) diff --git a/src/s_exp/mina/websocket/handler.clj b/src/s_exp/mina/websocket/handler.clj new file mode 100644 index 0000000..a1108d9 --- /dev/null +++ b/src/s_exp/mina/websocket/handler.clj @@ -0,0 +1,49 @@ +(ns s-exp.mina.websocket.handler + (:require [s-exp.mina.options :as options]) + (:import (io.helidon.common.buffers BufferData) + (io.helidon.http Headers) + (io.helidon.http HttpPrologue) + (io.helidon.webserver WebServerConfig$Builder) + (io.helidon.webserver.websocket WsRouting) + (io.helidon.websocket WsListener WsSession) + (java.util Optional))) + +(set! *warn-on-reflection* true) + +(defn make-listener + ^WsListener [{:as _listener + :keys [message ping pong close error open http-upgrade] + :or {message (constantly nil) + ping (constantly nil) + pong (constantly nil) + close (constantly nil) + error (constantly nil) + open (constantly nil) + http-upgrade (constantly (Optional/empty))}}] + (reify WsListener + (^void onMessage [_ ^WsSession session ^BufferData data ^boolean last?] + (message session data last?)) + (^void onPing [_ ^WsSession session ^BufferData data] + (ping session data)) + (^void onPong [_ ^WsSession session ^BufferData data] + (pong session data)) + (^void onClose [_ ^WsSession session ^int status ^String reason] + (close session status reason)) + (^void onError [_ ^WsSession session ^Throwable e] + (error session e)) + (^void onOpen [_ ^WsSession session] + (open session)) + (^Optional onHttpUpgrade [_ ^HttpPrologue http-prologue ^Headers headers] + (http-upgrade http-prologue headers)))) + +(defn set-websocket-handler! ^WebServerConfig$Builder + [^WebServerConfig$Builder builder [path listener] _options] + (doto builder + (.addRouting + (.build + (doto (WsRouting/builder) + (.endpoint path (make-listener listener))))))) + +(defmethod options/set-server-option! :websocket-handler + [^WebServerConfig$Builder builder _ handler options] + (set-websocket-handler! builder handler options)) diff --git a/test/s_exp/mina_test.clj b/test/s_exp/mina_test.clj index 234cbc1..d1f31bd 100644 --- a/test/s_exp/mina_test.clj +++ b/test/s_exp/mina_test.clj @@ -20,57 +20,57 @@ (finally (m/stop! server#)))))) (deftest test-send-headers - (with-server {:handler (fn [req] {:headers {:foo "bar"}})} + (with-server {:http-handler (fn [req] {:headers {:foo "bar"}})} (is (-> (client/get *endpoint*) :headers :foo (= "bar")))) - (with-server {:handler (fn [req] {:headers {:foo ["bar" "baz"]}})} + (with-server {:http-handler (fn [req] {:headers {:foo ["bar" "baz"]}})} (is (-> (client/get *endpoint*) :headers :foo (= ["bar" "baz"]))))) (deftest test-status - (with-server {:handler (fn [req] {:status 201})} + (with-server {:http-handler (fn [req] {:status 201})} (is (-> (client/get *endpoint*) :status (= 201))))) (deftest test-query-string - (with-server {:handler (fn [req] {:body (:query-string req)})} + (with-server {:http-handler (fn [req] {:body (:query-string req)})} (is (-> (client/get (str *endpoint* "?foo=bar")) :body (= "foo=bar")))) - (with-server {:handler (fn [req] {:body (:query-string req)})} + (with-server {:http-handler (fn [req] {:body (:query-string req)})} (is (-> (client/get (str *endpoint* "?")) :body (= "")))) - (with-server {:handler (fn [req] {:body (:query-string req)})} + (with-server {:http-handler (fn [req] {:body (:query-string req)})} (is (-> (client/get (str *endpoint* "")) :body (= ""))))) (deftest test-method - (with-server {:handler (fn [req] {:body (str (:request-method req))})} + (with-server {:http-handler (fn [req] {:body (str (:request-method req))})} (is (-> (client/post *endpoint*) :body (= ":post")))) - (with-server {:handler (fn [req] {:body (str (:request-method req))})} + (with-server {:http-handler (fn [req] {:body (str (:request-method req))})} (is (-> (client/put *endpoint*) :body (= ":put")))) - (with-server {:handler (fn [req] {:body (str (:request-method req))})} + (with-server {:http-handler (fn [req] {:body (str (:request-method req))})} (is (-> (client/delete *endpoint*) :body (= ":delete"))))) (deftest test-uri - (with-server {:handler (fn [req] {:body (:uri req)})} + (with-server {:http-handler (fn [req] {:body (:uri req)})} (is (-> (client/delete (str *endpoint* "foo/bar")) :body (= "/foo/bar"))))) (deftest test-scheme - (with-server {:handler (fn [req] {:body (str (:scheme req))})} + (with-server {:http-handler (fn [req] {:body (str (:scheme req))})} (is (-> (client/get *endpoint*) :body (= ":http"))))) (deftest test-body - (with-server {:handler (fn [req] {})} + (with-server {:http-handler (fn [req] {})} (is (-> (client/get *endpoint*) :body (= "")))) - (with-server {:handler (fn [req] {:body "yes"})} + (with-server {:http-handler (fn [req] {:body "yes"})} (is (-> (client/get *endpoint*) :body (= "yes")))) - (with-server {:handler (fn [req] {:body ["yes" "no"]})} + (with-server {:http-handler (fn [req] {:body ["yes" "no"]})} (is (-> (client/get *endpoint*) :body (= "yesno")))) - (with-server {:handler (fn [req] {:body (.getBytes "yes")})} + (with-server {:http-handler (fn [req] {:body (.getBytes "yes")})} (is (-> (client/get *endpoint*) :body (= "yes")))) - (with-server {:handler (fn [req] {:body (java.io.ByteArrayInputStream. (.getBytes "yes"))})} + (with-server {:http-handler (fn [req] {:body (java.io.ByteArrayInputStream. (.getBytes "yes"))})} (is (-> (client/get *endpoint*) :body (= "yes"))))) (defn tls [] @@ -84,7 +84,7 @@ (.build b))) (deftest test-ssl-context - (with-server {:handler (fn [req] {}) :tls (tls)} + (with-server {:http-handler (fn [req] {}) :tls (tls)} (let [endpoint (str/replace *endpoint* "http://" "https://")] (is (thrown? Exception (client/get endpoint))) (is (status-ok? (client/get endpoint