update jetty adapter to just use the jetty instance pulled in by ring
this also happens to be jetty 9, which is good as 7 and 8 are EOL
This commit is contained in:
parent
73bd151893
commit
579945fbda
|
@ -11,7 +11,7 @@
|
||||||
[clj-pebble "0.2.0"]
|
[clj-pebble "0.2.0"]
|
||||||
[prismatic/dommy "1.1.0"]
|
[prismatic/dommy "1.1.0"]
|
||||||
[gered/clj-browserchannel "0.3"]
|
[gered/clj-browserchannel "0.3"]
|
||||||
[gered/clj-browserchannel-jetty-adapter "0.0.9"]
|
[gered/clj-browserchannel-jetty-adapter "0.1.0"]
|
||||||
[gered/clj-browserchannel-immutant-adapter "0.0.1"]
|
[gered/clj-browserchannel-immutant-adapter "0.0.1"]
|
||||||
[org.immutant/web "2.1.4"]
|
[org.immutant/web "2.1.4"]
|
||||||
[environ "1.0.3"]]
|
[environ "1.0.3"]]
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
(defn run-jetty []
|
(defn run-jetty []
|
||||||
(println "Using Jetty adapter")
|
(println "Using Jetty adapter")
|
||||||
(jetty/run-jetty-async
|
(jetty/run-jetty
|
||||||
#'handler
|
#'handler
|
||||||
{:join? false
|
{:join? false
|
||||||
:port 8080}))
|
:port 8080}))
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
(defn -main [& args]
|
(defn -main [& args]
|
||||||
(if (env :dev) (pebble/set-options! :cache false))
|
(if (env :dev) (pebble/set-options! :cache false))
|
||||||
|
|
||||||
;(run-jetty)
|
(run-jetty)
|
||||||
(run-immutant)
|
;(run-immutant)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
# clj-browserchannel-jetty-adapter
|
# clj-browserchannel-jetty-adapter
|
||||||
|
|
||||||
Jetty async adapter for BrowserChannel
|
Jetty async adapter for BrowserChannel. This now simply makes use of
|
||||||
|
whatever Jetty version that Ring's [ring-jetty-adapter][1] is using
|
||||||
|
and just adds the required async handling configuration on top of it.
|
||||||
|
[1]:https://github.com/ring-clojure/ring/tree/master/ring-jetty-adapter
|
||||||
|
|
||||||
See also: [clj-browserchannel][1]
|
See also: [clj-browserchannel][1]
|
||||||
[1]:https://github.com/gered/clj-browserchannel
|
[1]:https://github.com/gered/clj-browserchannel
|
||||||
|
|
||||||
|
## Leiningen
|
||||||
|
|
||||||
|
[gered/clj-browserchannel-jetty-adapter "0.1.0"]
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
Written by:
|
Written by:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(defproject gered/clj-browserchannel-jetty-adapter "0.0.9"
|
(defproject gered/clj-browserchannel-jetty-adapter "0.1.0"
|
||||||
:description "Jetty async adapter for BrowserChannel"
|
:description "Jetty async adapter for BrowserChannel"
|
||||||
:dependencies [[ring/ring-core "1.4.0"]
|
:dependencies [[ring/ring-core "1.4.0"]
|
||||||
[ring/ring-servlet "1.4.0"]
|
[ring/ring-servlet "1.4.0"]
|
||||||
[org.eclipse.jetty/jetty-server "8.1.16.v20140903"];; includes ssl
|
[ring/ring-jetty-adapter "1.4.0"]
|
||||||
[gered/clj-browserchannel "0.3"]]
|
[gered/clj-browserchannel "0.3"]]
|
||||||
:profiles {:provided
|
:profiles {:provided
|
||||||
{:dependencies
|
{:dependencies
|
||||||
|
|
|
@ -2,14 +2,11 @@
|
||||||
"BrowserChannel adapter for the Jetty webserver, with async HTTP."
|
"BrowserChannel adapter for the Jetty webserver, with async HTTP."
|
||||||
(:import
|
(:import
|
||||||
[org.eclipse.jetty.server.handler AbstractHandler]
|
[org.eclipse.jetty.server.handler AbstractHandler]
|
||||||
[org.eclipse.jetty.server Server Request Response]
|
[org.eclipse.jetty.server Server Request]
|
||||||
[org.eclipse.jetty.server.nio SelectChannelConnector]
|
[javax.servlet AsyncContext AsyncListener AsyncEvent]
|
||||||
[org.eclipse.jetty.server.ssl SslSelectChannelConnector]
|
[javax.servlet.http HttpServletRequest])
|
||||||
[org.eclipse.jetty.util.ssl SslContextFactory]
|
|
||||||
[org.eclipse.jetty.continuation Continuation ContinuationSupport ContinuationListener]
|
|
||||||
[javax.servlet.http HttpServletRequest]
|
|
||||||
[java.security KeyStore])
|
|
||||||
(:require
|
(:require
|
||||||
|
[ring.adapter.jetty :as jetty]
|
||||||
[ring.util.servlet :as servlet]
|
[ring.util.servlet :as servlet]
|
||||||
[net.thegeez.browserchannel.async-adapter :as async-adapter]))
|
[net.thegeez.browserchannel.async-adapter :as async-adapter]))
|
||||||
|
|
||||||
|
@ -18,44 +15,26 @@
|
||||||
;; This has failed write support
|
;; This has failed write support
|
||||||
|
|
||||||
(deftype JettyAsyncResponse
|
(deftype JettyAsyncResponse
|
||||||
[^Continuation continuation]
|
[^AsyncContext async-context]
|
||||||
async-adapter/IAsyncAdapter
|
async-adapter/IAsyncAdapter
|
||||||
|
|
||||||
(head [this status headers]
|
(head [this status headers]
|
||||||
(doto (.getServletResponse continuation)
|
(doto (.getResponse async-context)
|
||||||
(servlet/update-servlet-response {:status status :headers (assoc headers "Transfer-Encoding" "chunked")})
|
(servlet/update-servlet-response {:status status :headers (assoc headers "Transfer-Encoding" "chunked")})
|
||||||
(.flushBuffer)))
|
(.flushBuffer)))
|
||||||
|
|
||||||
(write-chunk [this data]
|
(write-chunk [this data]
|
||||||
(doto (.getWriter (.getServletResponse continuation))
|
(doto (.getWriter (.getResponse async-context))
|
||||||
(.write ^String data)
|
(.write ^String data)
|
||||||
(.flush))
|
(.flush))
|
||||||
(when (.checkError (.getWriter (.getServletResponse continuation)))
|
(when (.checkError (.getWriter (.getResponse async-context)))
|
||||||
(throw async-adapter/ConnectionClosedException)))
|
(throw async-adapter/ConnectionClosedException)))
|
||||||
|
|
||||||
(close [this]
|
(close [this]
|
||||||
(doto (.getWriter (.getServletResponse continuation))
|
(doto (.getWriter (.getResponse async-context))
|
||||||
(.write "")
|
(.write "")
|
||||||
(.flush))
|
(.flush))
|
||||||
(.complete continuation)))
|
(.complete async-context)))
|
||||||
|
|
||||||
(defn- add-ssl-connector!
|
|
||||||
"Add an SslSelectChannelConnector to a Jetty Server instance."
|
|
||||||
[^Server server options]
|
|
||||||
(let [ssl-context-factory (SslContextFactory.)]
|
|
||||||
(doto ssl-context-factory
|
|
||||||
(.setKeyStorePath (options :keystore))
|
|
||||||
(.setKeyStorePassword (options :key-password)))
|
|
||||||
(when (options :truststore)
|
|
||||||
(.setTrustStore ssl-context-factory ^KeyStore (options :truststore)))
|
|
||||||
(when (options :trust-password)
|
|
||||||
(.setTrustStorePassword ssl-context-factory (options :trust-password)))
|
|
||||||
(when (options :include-cipher-suites)
|
|
||||||
(.setIncludeCipherSuites ssl-context-factory (into-array (options :include-cipher-suites))))
|
|
||||||
(when (options :include-protocols)
|
|
||||||
(.setIncludeProtocols ssl-context-factory (into-array (options :include-protocols))))
|
|
||||||
(let [conn (SslSelectChannelConnector. ssl-context-factory)]
|
|
||||||
(.addConnector server (doto conn (.setPort (options :ssl-port 8443)))))))
|
|
||||||
|
|
||||||
(defn- proxy-handler
|
(defn- proxy-handler
|
||||||
"Returns an Jetty Handler implementation for the given Ring handler."
|
"Returns an Jetty Handler implementation for the given Ring handler."
|
||||||
|
@ -64,52 +43,49 @@
|
||||||
(handle [target ^Request base-request ^HttpServletRequest request response]
|
(handle [target ^Request base-request ^HttpServletRequest request response]
|
||||||
(let [request-map (servlet/build-request-map request)
|
(let [request-map (servlet/build-request-map request)
|
||||||
response-map (handler request-map)]
|
response-map (handler request-map)]
|
||||||
(condp = (:async response-map)
|
(when response-map
|
||||||
nil
|
(condp = (:async response-map)
|
||||||
(do
|
nil
|
||||||
(servlet/update-servlet-response response response-map)
|
(do
|
||||||
(.setHandled base-request true))
|
(servlet/update-servlet-response response response-map)
|
||||||
:http
|
(.setHandled base-request true))
|
||||||
(let [reactor (:reactor response-map)
|
|
||||||
continuation ^Continuation (.startAsync request) ;; continuation lives until written to!
|
|
||||||
emit (JettyAsyncResponse. continuation)]
|
|
||||||
(.addContinuationListener continuation
|
|
||||||
(proxy [ContinuationListener] []
|
|
||||||
(onComplete [c] nil)
|
|
||||||
(onTimeout [^Continuation c] (.complete c))))
|
|
||||||
|
|
||||||
;; 4 minutes is google default
|
:http
|
||||||
(.setTimeout continuation (get options :response-timeout (* 4 60 1000)))
|
(let [reactor (:reactor response-map)
|
||||||
(reactor emit)))))))
|
async-context ^AsyncContext (.startAsync request) ;; continuation lives until written to!
|
||||||
|
emit (JettyAsyncResponse. async-context)]
|
||||||
|
(.addListener async-context
|
||||||
|
(proxy [AsyncListener] []
|
||||||
|
(onComplete [^AsyncEvent e]
|
||||||
|
nil)
|
||||||
|
(onTimeout [^AsyncEvent e]
|
||||||
|
(let [async-context ^AsyncContext (.getAsyncContext e)]
|
||||||
|
(.complete async-context)))))
|
||||||
|
|
||||||
(defn- create-server
|
;; 4 minutes is google default
|
||||||
"Construct a Jetty Server instance."
|
(.setTimeout async-context (get options :response-timeout (* 4 60 1000)))
|
||||||
[options]
|
(reactor emit))))))))
|
||||||
(let [connector (doto (SelectChannelConnector.)
|
|
||||||
(.setPort (options :port 80))
|
|
||||||
(.setHost (options :host)))
|
|
||||||
server (doto (Server.)
|
|
||||||
(.addConnector connector)
|
|
||||||
(.setSendDateHeader true))]
|
|
||||||
(when (or (options :ssl?) (options :ssl-port))
|
|
||||||
(add-ssl-connector! server options))
|
|
||||||
server))
|
|
||||||
|
|
||||||
(defn ^Server run-jetty-async
|
(defn- configure-jetty-async!
|
||||||
"Serve the given handler according to the options.
|
[^Server server handler options]
|
||||||
Options:
|
(.setHandler server (proxy-handler handler options)))
|
||||||
:configurator - A function called with the Server instance.
|
|
||||||
:port
|
(defn ^Server run-jetty
|
||||||
:host
|
"Starts a Jetty webserver to serve the given handler with the
|
||||||
:join? - Block the caller: defaults to true.
|
given options. This Jetty instance will have additional async
|
||||||
:response-timeout - Timeout after which the server will close the connection"
|
support necessary for BrowserChannel sessions.
|
||||||
|
|
||||||
|
The available options are the same as those used by
|
||||||
|
ring.adapter.jetty/run-jetty, except for these additions:
|
||||||
|
|
||||||
|
:response-timeout - Timeout after which the server will close the connection.
|
||||||
|
Specified in milliseconds, default is 4 minutes which is
|
||||||
|
the timeout period Google uses."
|
||||||
[handler options]
|
[handler options]
|
||||||
(let [^Server s (create-server (dissoc options :configurator))]
|
(let [existing-configurator (:configurator options)
|
||||||
(when-let [configurator (:configurator options)]
|
options (assoc options
|
||||||
(configurator s))
|
:configurator (fn [^Server server]
|
||||||
(doto s
|
(if existing-configurator
|
||||||
(.setHandler (proxy-handler handler options))
|
(existing-configurator server))
|
||||||
(.start))
|
(configure-jetty-async! server handler options)))]
|
||||||
(when (:join? options true)
|
(jetty/run-jetty handler options)))
|
||||||
(.join s))
|
|
||||||
s))
|
|
||||||
|
|
Reference in a new issue