From 579945fbdacc6a4f250f168ac1895daa2cf8cea4 Mon Sep 17 00:00:00 2001 From: gered Date: Mon, 9 May 2016 19:09:07 -0400 Subject: [PATCH] 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 --- chat-demo/project.clj | 2 +- chat-demo/src/chat_demo/server.clj | 6 +- clj-browserchannel-jetty-adapter/README.md | 9 +- clj-browserchannel-jetty-adapter/project.clj | 4 +- .../browserchannel/jetty_async_adapter.clj | 128 +++++++----------- 5 files changed, 66 insertions(+), 83 deletions(-) diff --git a/chat-demo/project.clj b/chat-demo/project.clj index 0e0771c..46586ed 100644 --- a/chat-demo/project.clj +++ b/chat-demo/project.clj @@ -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"]] diff --git a/chat-demo/src/chat_demo/server.clj b/chat-demo/src/chat_demo/server.clj index 2c13ce3..8b76812 100644 --- a/chat-demo/src/chat_demo/server.clj +++ b/chat-demo/src/chat_demo/server.clj @@ -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) ) diff --git a/clj-browserchannel-jetty-adapter/README.md b/clj-browserchannel-jetty-adapter/README.md index 0766588..14f7f02 100644 --- a/clj-browserchannel-jetty-adapter/README.md +++ b/clj-browserchannel-jetty-adapter/README.md @@ -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: diff --git a/clj-browserchannel-jetty-adapter/project.clj b/clj-browserchannel-jetty-adapter/project.clj index 424c5aa..8c4fe8c 100644 --- a/clj-browserchannel-jetty-adapter/project.clj +++ b/clj-browserchannel-jetty-adapter/project.clj @@ -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 diff --git a/clj-browserchannel-jetty-adapter/src/net/thegeez/browserchannel/jetty_async_adapter.clj b/clj-browserchannel-jetty-adapter/src/net/thegeez/browserchannel/jetty_async_adapter.clj index 581ae8b..fdd2653 100644 --- a/clj-browserchannel-jetty-adapter/src/net/thegeez/browserchannel/jetty_async_adapter.clj +++ b/clj-browserchannel-jetty-adapter/src/net/thegeez/browserchannel/jetty_async_adapter.clj @@ -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)] - (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)))) + (when response-map + (condp = (:async response-map) + nil + (do + (servlet/update-servlet-response response response-map) + (.setHandled base-request true)) - ;; 4 minutes is google default - (.setTimeout continuation (get options :response-timeout (* 4 60 1000))) - (reactor emit))))))) + :http + (let [reactor (:reactor response-map) + 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 - "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)) + ;; 4 minutes is google default + (.setTimeout async-context (get options :response-timeout (* 4 60 1000))) + (reactor emit)))))))) -(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- configure-jetty-async! + [^Server server handler options] + (.setHandler server (proxy-handler handler options))) + +(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)))