Skip to content

Commit

Permalink
Add unix domain socket support
Browse files Browse the repository at this point in the history
Signed-off-by: Loukas Agorgianitis <[email protected]>
  • Loading branch information
agorgl committed Sep 27, 2024
1 parent 7d54a32 commit 3fff1d8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
2 changes: 2 additions & 0 deletions ring-jetty-adapter/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
[ring/ring-core "1.12.2"]
[org.ring-clojure/ring-jakarta-servlet "1.12.2"]
[org.eclipse.jetty/jetty-server "11.0.21"]
[org.eclipse.jetty/jetty-unixdomain-server "11.0.21"]
[org.eclipse.jetty.websocket/websocket-jetty-server "11.0.21"]]
:aliases {"test-all" ["with-profile" "default:+1.10:+1.11:+1.12" "test"]}
:profiles
{:dev {:dependencies [[clj-http "3.13.0"]
[less-awful-ssl "1.0.6"]
[hato "0.9.0"]]
:jvm-opts ["-Dorg.eclipse.jetty.server.HttpChannelState.DEFAULT_TIMEOUT=500"]}
:test {:dependencies [[org.eclipse.jetty/jetty-client "11.0.21"]]}
:1.10 {:dependencies [[org.clojure/clojure "1.10.3"]]}
:1.11 {:dependencies [[org.clojure/clojure "1.11.2"]]}
:1.12 {:dependencies [[org.clojure/clojure "1.12.0-alpha9"]]}})
19 changes: 18 additions & 1 deletion ring-jetty-adapter/src/ring/adapter/jetty.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"A Ring adapter that uses the Jetty 9 embedded web server.
Adapters are used to convert Ring handlers into running web servers."
(:require [ring.util.jakarta.servlet :as servlet]
(:require [clojure.java.io :as io]
[ring.util.jakarta.servlet :as servlet]
[ring.websocket :as ws]
[ring.websocket.protocols :as wsp])
(:import [java.nio ByteBuffer]
Expand All @@ -15,6 +16,7 @@
HttpConnectionFactory
SslConnectionFactory
SecureRequestCustomizer]
[org.eclipse.jetty.unixdomain.server UnixDomainServerConnector]
[org.eclipse.jetty.servlet ServletContextHandler ServletHandler]
[org.eclipse.jetty.util BlockingArrayQueue]
[org.eclipse.jetty.util.thread ThreadPool QueuedThreadPool]
Expand Down Expand Up @@ -161,6 +163,10 @@
(ServerConnector. server #^"[Lorg.eclipse.jetty.server.ConnectionFactory;"
(into-array ConnectionFactory factories)))

(defn- unix-domain-server-connector ^UnixDomainServerConnector [^Server server & factories]
(UnixDomainServerConnector. server #^"[Lorg.eclipse.jetty.server.ConnectionFactory;"
(into-array ConnectionFactory factories)))

(defn- http-config ^HttpConfiguration [options]
(doto (HttpConfiguration.)
(.setSendDateHeader (:send-date-header? options true))
Expand Down Expand Up @@ -229,6 +235,14 @@
(.setHost (options :host))
(.setIdleTimeout (options :max-idle-time 200000)))))

(defn- unix-socket-connector ^ServerConnector [server options]
(let [http-factory (HttpConnectionFactory. (http-config options))
socket (io/file (options :unix-socket))]
(.deleteOnExit socket)
(doto (unix-domain-server-connector server http-factory)
(.setUnixDomainPath (.toPath socket))
(.setIdleTimeout (options :max-idle-time 200000)))))

(defn- create-threadpool [options]
(let [min-threads (options :min-threads 8)
max-threads (options :max-threads 50)
Expand All @@ -253,6 +267,8 @@
(.addConnector server (http-connector server options)))
(when (or (options :ssl?) (options :ssl-port))
(.addConnector server (ssl-connector server options)))
(when (options :unix-socket)
(.addConnector server (unix-socket-connector server options)))
server))

(defn run-jetty
Expand All @@ -266,6 +282,7 @@
:async-timeout-handler - an async handler to handle an async context timeout
:port - the port to listen on (defaults to 80)
:host - the hostname to listen on
:unix-socket - the unix domain docket path to listen on
:join? - blocks the thread until server ends
(defaults to true)
:daemon? - use daemon threads (defaults to false)
Expand Down
28 changes: 27 additions & 1 deletion ring-jetty-adapter/test/ring/adapter/test/jetty.clj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
[ring.core.protocols :as p]
[ring.websocket :as ws]
[ring.websocket.protocols :as wsp])
(:import [java.nio ByteBuffer]
(:import [java.io File]
[java.nio ByteBuffer]
[java.nio.file Paths]
[org.eclipse.jetty.util.thread QueuedThreadPool]
[org.eclipse.jetty.server Server Request SslConnectionFactory]
[org.eclipse.jetty.server.handler AbstractHandler]
[org.eclipse.jetty.io ClientConnector]
[org.eclipse.jetty.client HttpClient]
[org.eclipse.jetty.client.http HttpClientTransportOverHTTP]
[java.net ServerSocket ConnectException]
[java.security KeyStore]
[java.io SequenceInputStream ByteArrayInputStream InputStream
Expand Down Expand Up @@ -81,6 +86,11 @@

(def test-ssl-url (str "https://localhost:" test-ssl-port))

(def test-unix-domain-socket
(let [sock-file (File/createTempFile "ring-jetty-" ".sock")]
(.delete sock-file)
(.getAbsolutePath sock-file)))

(def nil-keystore
(doto (KeyStore/getInstance (KeyStore/getDefaultType)) (.load nil)))

Expand All @@ -102,6 +112,22 @@
"text/plain"))
(is (= (:body response) "Hello World")))))

(let [java-version (->> (System/getProperty "java.version")
(re-find #"\A\d+")
(Integer/parseInt))]
(when (>= java-version 16)
(testing "UNIX Socket server"
(with-server hello-world {:http? false
:unix-socket test-unix-domain-socket}
(let [path (Paths/get test-unix-domain-socket (make-array String 0))
connector (ClientConnector/forUnixDomain path)
transport (HttpClientTransportOverHTTP. connector)
client (doto (HttpClient. transport) (.start))
response (.GET client "http://localhost")]
(is (= (.getStatus response) 200))
(is (.getMediaType response) "text/plain")
(is (= (.getContentAsString response) "Hello World")))))))

(testing "HTTPS server"
(with-server hello-world {:port test-port
:ssl-port test-ssl-port
Expand Down

0 comments on commit 3fff1d8

Please sign in to comment.