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:
Gered 2016-05-09 19:09:07 -04:00
parent 73bd151893
commit 579945fbda
5 changed files with 66 additions and 83 deletions

View file

@ -11,7 +11,7 @@
[clj-pebble "0.2.0"]
[prismatic/dommy "1.1.0"]
[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"]
[org.immutant/web "2.1.4"]
[environ "1.0.3"]]

View file

@ -44,7 +44,7 @@
(defn run-jetty []
(println "Using Jetty adapter")
(jetty/run-jetty-async
(jetty/run-jetty
#'handler
{:join? false
:port 8080}))
@ -58,7 +58,7 @@
(defn -main [& args]
(if (env :dev) (pebble/set-options! :cache false))
;(run-jetty)
(run-immutant)
(run-jetty)
;(run-immutant)
)

View file

@ -1,10 +1,17 @@
# 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]
[1]:https://github.com/gered/clj-browserchannel
## Leiningen
[gered/clj-browserchannel-jetty-adapter "0.1.0"]
## About
Written by:

View file

@ -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"
:dependencies [[ring/ring-core "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"]]
:profiles {:provided
{:dependencies

View file

@ -2,14 +2,11 @@
"BrowserChannel adapter for the Jetty webserver, with async HTTP."
(:import
[org.eclipse.jetty.server.handler AbstractHandler]
[org.eclipse.jetty.server Server Request Response]
[org.eclipse.jetty.server.nio SelectChannelConnector]
[org.eclipse.jetty.server.ssl SslSelectChannelConnector]
[org.eclipse.jetty.util.ssl SslContextFactory]
[org.eclipse.jetty.continuation Continuation ContinuationSupport ContinuationListener]
[javax.servlet.http HttpServletRequest]
[java.security KeyStore])
[org.eclipse.jetty.server Server Request]
[javax.servlet AsyncContext AsyncListener AsyncEvent]
[javax.servlet.http HttpServletRequest])
(:require
[ring.adapter.jetty :as jetty]
[ring.util.servlet :as servlet]
[net.thegeez.browserchannel.async-adapter :as async-adapter]))
@ -18,44 +15,26 @@
;; This has failed write support
(deftype JettyAsyncResponse
[^Continuation continuation]
[^AsyncContext async-context]
async-adapter/IAsyncAdapter
(head [this status headers]
(doto (.getServletResponse continuation)
(doto (.getResponse async-context)
(servlet/update-servlet-response {:status status :headers (assoc headers "Transfer-Encoding" "chunked")})
(.flushBuffer)))
(write-chunk [this data]
(doto (.getWriter (.getServletResponse continuation))
(doto (.getWriter (.getResponse async-context))
(.write ^String data)
(.flush))
(when (.checkError (.getWriter (.getServletResponse continuation)))
(when (.checkError (.getWriter (.getResponse async-context)))
(throw async-adapter/ConnectionClosedException)))
(close [this]
(doto (.getWriter (.getServletResponse continuation))
(doto (.getWriter (.getResponse async-context))
(.write "")
(.flush))
(.complete continuation)))
(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)))))))
(.complete async-context)))
(defn- proxy-handler
"Returns an Jetty Handler implementation for the given Ring handler."
@ -64,52 +43,49 @@
(handle [target ^Request base-request ^HttpServletRequest request response]
(let [request-map (servlet/build-request-map request)
response-map (handler request-map)]
(when response-map
(condp = (:async response-map)
nil
(do
(servlet/update-servlet-response response response-map)
(.setHandled base-request true))
:http
(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))))
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)))))
;; 4 minutes is google default
(.setTimeout continuation (get options :response-timeout (* 4 60 1000)))
(reactor emit)))))))
(.setTimeout async-context (get options :response-timeout (* 4 60 1000)))
(reactor emit))))))))
(defn- create-server
"Construct a Jetty Server instance."
[options]
(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- configure-jetty-async!
[^Server server handler options]
(.setHandler server (proxy-handler handler options)))
(defn ^Server run-jetty-async
"Serve the given handler according to the options.
Options:
:configurator - A function called with the Server instance.
:port
:host
:join? - Block the caller: defaults to true.
:response-timeout - Timeout after which the server will close the connection"
(defn ^Server run-jetty
"Starts a Jetty webserver to serve the given handler with the
given options. This Jetty instance will have additional async
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]
(let [^Server s (create-server (dissoc options :configurator))]
(when-let [configurator (:configurator options)]
(configurator s))
(doto s
(.setHandler (proxy-handler handler options))
(.start))
(when (:join? options true)
(.join s))
s))
(let [existing-configurator (:configurator options)
options (assoc options
:configurator (fn [^Server server]
(if existing-configurator
(existing-configurator server))
(configure-jetty-async! server handler options)))]
(jetty/run-jetty handler options)))