-
Notifications
You must be signed in to change notification settings - Fork 517
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
Add support for serving on Unix domain socket #478
base: master
Are you sure you want to change the base?
Changes from all commits
d7e22d4
7a0ff20
c0aec47
9ede539
71ec504
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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.servlet :as servlet]) | ||
(:require [clojure.java.io :as io] | ||
[ring.util.servlet :as servlet]) | ||
(:import [org.eclipse.jetty.server | ||
Request | ||
Server | ||
|
@@ -13,11 +14,13 @@ | |
SslConnectionFactory | ||
SecureRequestCustomizer] | ||
[org.eclipse.jetty.server.handler AbstractHandler] | ||
[org.eclipse.jetty.unixsocket UnixSocketConnector] | ||
[org.eclipse.jetty.util BlockingArrayQueue] | ||
[org.eclipse.jetty.util.thread ThreadPool QueuedThreadPool] | ||
[org.eclipse.jetty.util.ssl SslContextFactory$Server KeyStoreScanner] | ||
[javax.servlet AsyncContext DispatcherType AsyncEvent AsyncListener] | ||
[javax.servlet.http HttpServletRequest HttpServletResponse])) | ||
(set! *warn-on-reflection* true) | ||
|
||
(defn- ^AbstractHandler proxy-handler [handler] | ||
(proxy [AbstractHandler] [] | ||
|
@@ -130,6 +133,25 @@ | |
(.setHost (options :host)) | ||
(.setIdleTimeout (options :max-idle-time 200000))))) | ||
|
||
(defn- socket-connector | ||
^UnixSocketConnector [^Server server {:keys [unix-socket] :as options}] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use a consistent format in this file, so: (defn- ^UnixSocketConnector unix-socket-connector
[^Server server {:keys [unix-socket] :as options}] Also I think |
||
(when (->> (System/getProperty "os.name") | ||
(re-find #"(?i)^windows")) | ||
(throw (ex-info "Unix sockets not supported on windows" | ||
{:os (System/getProperty "os.name") | ||
:unix-socket unix-socket}))) | ||
Comment on lines
+138
to
+142
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's factor this out into its own function (and also capitalize Windows): (defn- check-os-socket-compatibility []
(when (->> (System/getProperty "os.name")
(re-find #"(?i)^windows"))
(throw (ex-info "Unix sockets not supported on Windows"
{:os (System/getProperty "os.name")
:unix-socket unix-socket})))) |
||
(let [http-factory (HttpConnectionFactory. (http-config options)) | ||
socket (io/file unix-socket)] | ||
(when (.exists socket) | ||
(throw (ex-info "File already exists at socket path; should be deleted before starting server" | ||
{:unix-socket unix-socket}))) | ||
Comment on lines
+145
to
+147
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's factor this out as well: (defn- check-socket-file-does-not-exist [socket]
(when (.exists socket)
(throw (ex-info "Could not create socket file: file already exists"
{:socket-file (str socket)})))) |
||
(.deleteOnExit socket) | ||
(doto (UnixSocketConnector. | ||
server | ||
#^"[Lorg.eclipse.jetty.server.ConnectionFactory;" (into-array ConnectionFactory [http-factory])) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you split the line over 80 characters into two lines? Also can you fix the indentation so it's according to the style guide: (doto (UnixSocketConnector.
server
^"[Lorg.eclipse.jetty.server.ConnectionFactory;"
(into-array ConnectionFactory [http-factory])) |
||
(.setUnixSocket (.getAbsolutePath socket)) | ||
(.setIdleTimeout (options :max-idle-time 200000))))) | ||
|
||
(defn- ^ThreadPool create-threadpool [options] | ||
(let [min-threads (options :min-threads 8) | ||
max-threads (options :max-threads 50) | ||
|
@@ -150,10 +172,15 @@ | |
(defn- ^Server create-server [options] | ||
(let [pool (or (:thread-pool options) (create-threadpool options)) | ||
server (Server. pool)] | ||
(when (:http? options true) | ||
(when (:http? options (or ;; default is enabled when no socket specified | ||
(not (:unix-socket options)) | ||
;; enabled with socket when host/port set | ||
(some options [:host :port]))) | ||
Comment on lines
+175
to
+178
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels too complex, and isn't what the documentation says. I think let's keep it simple and just leave it defaulting to true. Let's add a note to the |
||
(.addConnector server (http-connector server options))) | ||
(when (or (options :ssl?) (options :ssl-port)) | ||
(.addConnector server (ssl-connector server options))) | ||
(when (:unix-socket options) | ||
(.addConnector server (socket-connector server options))) | ||
server)) | ||
|
||
(defn ^Server run-jetty | ||
|
@@ -170,10 +197,14 @@ | |
:join? - blocks the thread until server ends | ||
(defaults to true) | ||
:daemon? - use daemon threads (defaults to false) | ||
:http? - listen on :port for HTTP traffic (defaults to true) | ||
:http? - listen on :port for HTTP traffic (defaults to true | ||
unless :unix-socket is set) | ||
:ssl? - allow connections over HTTPS | ||
:ssl-port - the SSL port to listen on (defaults to 443, implies | ||
:ssl? is true) | ||
:unix-socket - File to be used as a Unix domain socket; will be | ||
passed to [io/file]. Ensure there is no file at | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think |
||
this location when starting the server. | ||
:ssl-context - an optional SSLContext to use for SSL connections | ||
:exclude-ciphers - when :ssl? is true, additionally exclude these | ||
cipher suites | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,12 @@ | |
[java.net ServerSocket ConnectException] | ||
[java.security KeyStore] | ||
[java.io SequenceInputStream ByteArrayInputStream InputStream | ||
IOException] | ||
[org.apache.http MalformedChunkCodingException])) | ||
IOException | ||
File] | ||
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two lines should be one. |
||
[java.util.function Supplier] | ||
[org.apache.http MalformedChunkCodingException] | ||
[io.netty.channel.unix DomainSocketAddress] | ||
[reactor.netty.http.client HttpClient])) | ||
|
||
(defn- hello-world [request] | ||
{:status 200 | ||
|
@@ -98,6 +102,23 @@ | |
"text/plain")) | ||
(is (= (:body response) "Hello World"))))) | ||
|
||
(testing "socket server" | ||
(let [sock (File/createTempFile "ring-jetty-server-" ".sock")] | ||
(.delete sock) | ||
(with-server hello-world {:unix-socket sock} | ||
(is (= (-> (HttpClient/create) | ||
(.remoteAddress | ||
(reify Supplier | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation looks off here. |
||
(get [_] | ||
(DomainSocketAddress. (.getAbsolutePath sock))))) | ||
.get (.uri "/") .responseContent .aggregate .asString .block) | ||
"Hello World") | ||
"able to serve basic request") | ||
(is (thrown-with-msg? | ||
clojure.lang.ExceptionInfo #"File already exists" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation looks off. Please see Clojure style guide. |
||
(run-jetty hello-world {:unix-socket sock, :join? false})) | ||
"starting a new server on existing socket should fail")))) | ||
|
||
(testing "HTTPS server" | ||
(with-server hello-world {:port test-port | ||
:ssl-port test-ssl-port | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove this line, please.