Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helidon m2 #6

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ jobs:
- name: Prepare java
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: '20'
distribution: 'zulu'
java-version: '21-ea'

- name: Install clojure tools
uses: DeLaGuardo/[email protected]
Expand Down
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,17 @@ middlewares out there.

* `:port` - port the server listens to, defaults to random free port

* `:default-socket` - map-of `:write-queue-length` `:backlog` `:max-payload-size` `:receive-buffer-size` `:connection-options`(map-of `:socket-receive-buffer-size` `:socket-send-buffer-size` `:socket-reuse-address` `:socket-keep-alive` `:tcp-no-delay` `:read-timeout` `:connect-timeout`)
* `:write-queue-length`

* `:backlog`

* `:max-payload-size`

* `:write-queue-length`

* `:receive-buffer-size`

* `:connection-options`(map-of `:socket-receive-buffer-size` `:socket-send-buffer-size` `:socket-reuse-address` `:socket-keep-alive` `:tcp-no-delay` `:read-timeout` `:connect-timeout`)

* `:tls` - A `io.helidon.nima.common.tls.Tls` instance

Expand All @@ -49,8 +59,7 @@ it will do the protocol switch automatically.

## Installation

Note: You need to use java20 and add `:jvm-opts ["--enable-preview"]` to the
alias you will use to be able to run it.
Note: You need to use java **21**

https://clojars.org/com.s-exp/mina

Expand Down
10 changes: 4 additions & 6 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@
:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.12.0-alpha1"}
com.github.strojure/zmap {:mvn/version "1.3.26"}

io.helidon.nima/helidon-nima {:mvn/version "4.0.0-ALPHA6"}
io.helidon.nima.webserver/helidon-nima-webserver {:mvn/version "4.0.0-ALPHA6"}
io.helidon.nima.http2/helidon-nima-http2-webserver {:mvn/version "4.0.0-ALPHA6"}}
io.helidon.http/helidon-http {:mvn/version "4.0.0-M2"}
io.helidon.webserver/helidon-webserver {:mvn/version "4.0.0-M2"}
io.helidon.webserver/helidon-webserver-http2 {:mvn/version "4.0.0-M2"}}

:aliases
{:test {:jvm-opts ["--enable-preview"]
:extra-paths ["test"]
{:test {:extra-paths ["test"]
: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"}
Expand Down
25 changes: 14 additions & 11 deletions src/s_exp/mina.clj
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
(ns s-exp.mina
(:require [s-exp.mina.handler]
[s-exp.mina.options :as options])
(:import (io.helidon.nima.webserver WebServer WebServer$Builder)))
(:import (io.helidon.webserver WebServer WebServerConfig WebServerConfig$Builder)))

(set! *warn-on-reflection* true)

(def default-options {:connection-provider false})

(defn- server-builder
^WebServer$Builder
^WebServerConfig$Builder
[options]
(reduce (fn [builder [k v]]
(options/set-server-option! builder k v options))
(WebServer/builder)
(WebServerConfig/builder)
options))

(defn start!
Expand All @@ -31,6 +31,7 @@
(start! (assoc options :handler handler)))
([options]
(-> (server-builder (merge default-options options))
.build
(.start))))

(defn stop!
Expand All @@ -39,16 +40,18 @@
(.stop server))

;; (def r {:status 200})
;; ;; (def h (fn [req]
;; ;; (prn (counted? (:headers req)))
;; ;; r))
;; ;; (def h (fn [_]
;; ;; ;; (prn :aasdf ((:headers _) "accept"))
;; ;; ;; (prn (:headers _))
;; ;; r))
;; (def h (fn [req]
;; (prn (counted? (:headers req)))
;; r))
;; (def h (fn [_]
;; ;; (prn :aasdf ((:headers _) "accept"))
;; ;; (prn (:headers _))
;; r))
;; (def s (start!
;; r
;; {:host "0.0.0.0" :port 8080 :default-socket {:write-queue-length 10240}}))
;; {:host "0.0.0.0" :port 8080
;; :write-queue-length 10240
;; :connection-options {:socket-send-buffer-size 1024}}))

;; (stop! s)

Expand Down
29 changes: 15 additions & 14 deletions src/s_exp/mina/handler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@
(:require [s-exp.mina.options :as options]
[s-exp.mina.request :as request]
[s-exp.mina.response :as response])
(:import (io.helidon.nima.webserver WebServer$Builder)
(io.helidon.nima.webserver.http Handler
HttpRouting)))
(:import (io.helidon.webserver WebServerConfig$Builder)
(io.helidon.webserver.http Handler
HttpRouting)))

(defn set-ring1-handler! ^WebServer$Builder
[^WebServer$Builder builder handler _options]
(defn set-ring1-handler! ^WebServerConfig$Builder
[^WebServerConfig$Builder builder handler _options]
(doto builder
(.addRouting
(doto (HttpRouting/builder)
(.any
(into-array Handler
[(reify Handler
(handle [_ server-request server-response]
(->> (request/ring-request server-request server-response)
handler
(response/set-response! server-response))))]))))))
(.build
(doto (HttpRouting/builder)
(.any
(into-array Handler
[(reify Handler
(handle [_ server-request server-response]
(->> (request/ring-request server-request server-response)
handler
(response/set-response! server-response))))])))))))

(defmethod options/set-server-option! :handler
[^WebServer$Builder builder _ handler options]
[^WebServerConfig$Builder builder _ handler options]
(set-ring1-handler! builder handler options))
72 changes: 32 additions & 40 deletions src/s_exp/mina/options.clj
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
(ns s-exp.mina.options
(:import (io.helidon.common.socket SocketOptions$Builder)
(io.helidon.nima.webserver ListenerConfiguration$Builder WebServer$Builder)
(io.helidon.common.tls Tls)
(io.helidon.webserver WebServerConfig$Builder)
(java.time Duration)))

(set! *warn-on-reflection* true)

(defmulti set-server-option! (fn [_builder k _v _options] k))

(defmethod set-server-option! :default [builder _ _ _]
builder)

(defmethod set-server-option! :host
[^WebServer$Builder builder _ host _]
[^WebServerConfig$Builder builder _ host _]
(.host builder host))

(defmethod set-server-option! :port
[^WebServer$Builder builder _ port _]
[^WebServerConfig$Builder builder _ port _]
(.port builder (int port)))

(defmethod set-server-option! :backlog
[^WebServerConfig$Builder builder _ backlog _]
(.backlog builder (int backlog)))

(defmethod set-server-option! :max-payload-size
[^WebServerConfig$Builder builder _ max-payload-size _]
(.maxPayloadSize builder (long max-payload-size)))

(defmethod set-server-option! :write-queue-length
[^WebServerConfig$Builder builder _ write-queue-length _]
(.writeQueueLength builder (long write-queue-length)))

(defmethod set-server-option! :receive-buffer-size
[^WebServerConfig$Builder builder _ receive-buffer-size _]
(.receiveBufferSize builder (int receive-buffer-size)))

(defn- set-connection-options!
[^SocketOptions$Builder socket-options-builder
{:keys [socket-receive-buffer-size socket-send-buffer-size
Expand Down Expand Up @@ -47,44 +66,17 @@
(.connectTimeout socket-options-builder
(Duration/ofMillis connect-timeout))))

(defn- set-listener-configuration!
[^ListenerConfiguration$Builder listener-configuration-builder
{:keys [write-queue-length backlog max-payload-size receive-buffer-size
connection-options]}]
(when backlog
(.backlog listener-configuration-builder
(int backlog)))

(when max-payload-size
(.maxPayloadSize listener-configuration-builder
(long max-payload-size)))

(when write-queue-length
(.writeQueueLength listener-configuration-builder
(int write-queue-length)))

(when receive-buffer-size
(.receiveBufferSize listener-configuration-builder
(int receive-buffer-size)))

(when (seq connection-options)
(.connectionOptions listener-configuration-builder
(reify java.util.function.Consumer
(accept [_ socket-options-builder]
(set-connection-options! socket-options-builder
connection-options))))))

(defmethod set-server-option! :default-socket
[^WebServer$Builder builder _ default-socket _]
(doto builder
(.defaultSocket
(reify java.util.function.Consumer
(accept [_ listener-configuration-builder]
(set-listener-configuration! listener-configuration-builder
default-socket))))))
(defmethod set-server-option! :connection-options
[^WebServerConfig$Builder builder _ connection-options _]
(.connectionOptions builder
(reify java.util.function.Consumer
(accept [_ socket-options-builder]
(prn :sob socket-options-builder)
(set-connection-options! socket-options-builder
connection-options)))))

(defmethod set-server-option! :tls
[^WebServer$Builder builder _ tls _]
(doto builder (.tls tls)))
[^WebServerConfig$Builder builder _ tls-config _]
(doto builder (.tls ^Tls tls-config)))


33 changes: 17 additions & 16 deletions src/s_exp/mina/request.clj
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,39 @@
MapEquivalence
PersistentHashMap
Util)
(io.helidon.common.http
(io.helidon.http
Headers
Http$Header
Http$HeaderName
Http$HeaderValue
Http$HeaderNames
ServerRequestHeaders)
(io.helidon.nima.webserver.http ServerRequest ServerResponse)
(io.helidon.webserver.http ServerRequest ServerResponse)
(java.util Map)))

(defn header-name ^Http$HeaderName
[s]
(Http$Header/createFromLowercase s))
(Http$HeaderNames/createFromLowercase s))

(defn header->value*
([^Http$Header header header-name]
([^Headers header header-name]
(header->value* header header-name nil))
([^Http$Header header header-name not-found]
([^Headers header
^Http$HeaderName header-name not-found]
(-> header
(.value header-name)
(.orElse not-found))))

(defn header->value
([^Http$Header h k]
([^Headers h k]
(header->value h k nil))
([^Http$Header h k not-found]
([^Headers h k not-found]
(header->value* h
(header-name k)
not-found)))

(defn ring-headers*
[^ServerRequestHeaders headers]
(-> (reduce (fn [m ^Http$HeaderValue h]
[^Headers headers]
(-> (reduce (fn [m ^Http$Header h]
(assoc! m
(.lowerCase (.headerName h))
(.value h)))
Expand All @@ -49,7 +51,7 @@
persistent!))

(defprotocol RingHeaders
(ring-headers [_]))
(^clojure.lang.APersistentMap ring-headers [_]))

(defn ring-method
[^ServerRequest server-request]
Expand Down Expand Up @@ -80,7 +82,7 @@
"2.0" "HTTP/2"))

;; inspired by ring-undertow
(deftype HeaderMapProxy [^ServerRequestHeaders headers
(deftype HeaderMapProxy [^Headers headers
^:volatile-mutable persistent-copy]
Map
(size [_]
Expand Down Expand Up @@ -144,11 +146,10 @@

(iterator [_]
(->> headers
(eduction (map (fn [header]
.iterator
(eduction (map (fn [^Http$Header header]
(MapEntry. (.lowerCase (.headerName header))
(.value header)))))

.iterator))
(.value header)))))))

IKVReduce
(kvreduce [this f init]
Expand Down
21 changes: 9 additions & 12 deletions src/s_exp/mina/response.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
(ns s-exp.mina.response
(:require [s-exp.mina.utils :as u])
(:import (io.helidon.common.http HeaderEnum Http$Header Http$Status)
(io.helidon.nima.webserver.http ServerResponse)
(:import (io.helidon.http Http$Headers
Http$HeaderNames
Http$HeaderName
Http$Status)
(io.helidon.webserver.http ServerResponse)
(java.io FileInputStream InputStream OutputStream)))

(defprotocol BodyWriter
Expand Down Expand Up @@ -34,21 +36,16 @@
(write-body! [o server-response]
(.send ^ServerResponse server-response o)))

(def header-name
(eval `(fn [ring-header-key#]
(case ring-header-key#
~@(mapcat (fn [[k v]]
[k (symbol "io.helidon.common.http.Http$Header" (.name v))])
(u/enum->map HeaderEnum))
(Http$Header/create (name ring-header-key#))))))
(defn header-name ^Http$HeaderName [ring-header-name]
(Http$HeaderNames/createFromLowercase (name ring-header-name)))

(defn set-headers!
[^ServerResponse server-response headers]
(when headers
(run! (fn [[k v]]
(.header server-response
(Http$Header/create (header-name k)
v)))
(Http$Headers/create (header-name k)
v)))
headers)))

(defn- set-status!
Expand Down
Loading