           (servlet/update-servlet-response response response-map)
           (.setHandled base-request true))))))
 
+;;; Monkey patch the private function. Yes, you can do this. No, you shouldn't have to.
+
 (let [proxy-handler-var (-> 'ring.adapter.jetty ns-map (get 'proxy-handler))]
   (alter-var-root proxy-handler-var (constantly customized-proxy-handler)))
 
-;; Although we could move some of this code into customized-proxy-handler, that
-;; would be problematic for any application which happens to load this namespace,
-;; but doesn't actually run the server async. This is reasonable that a server
-;; may run multiple instances of Jetty, some for asynchronous web services in Rook,
-;; others as standard synchronous web servers or services.  The customized proxy handler
-;; is benign if async is not actually used.
+;;; Although we could move some of this code into customized-proxy-handler, that
+;;; would be problematic for any application which happens to load this namespace,
+;;; but doesn't actually run the server async. This is reasonable in a server
+;;; that runs multiple instances of Jetty, some for asynchronous web services in Rook,
+;;; others as standard synchronous web servers or services.  The customized proxy handler
+;;; is benign if async is not actually used.
 
 (defn- wrap-with-continuation
-  [handler]
+  [handler timeout-ms]
   (fn [request]
     (let [^HttpServletRequest req (::http-servlet-request request)
           ^HttpServletResponse res (::http-servlet-response request)
           ^Continuation continuation (ContinuationSupport/getContinuation req)]
       (.suspend continuation res)
       (go
-        (let [response-map (-> request
-                               (dissoc ::http-servlet-request ::http-servlet-response)
-                               handler
-                               <!)]
+        (let [response-ch (-> request
+                              (dissoc ::http-servlet-request ::http-servlet-response)
+                              handler)
+              ;; Jetty can do a timeout, but we have our own.
+              [response] (alts! [response-ch (timeout timeout-ms)])]
+
+          (if response
+            (l/debugf "Asynchronous response:%n%s" (utils/pretty-print response))
+            (l/warnf "Request %s `%s' timed out after %d ms."
+                     (-> request :request-method name .toString .toUpperCase)
+                     (-> request :uri)
+                     timeout-ms))
+
           (-> continuation
               .getServletResponse
-              (servlet/update-servlet-response response-map))
+              (servlet/update-servlet-response
+                (or response
+                    {:status HttpServletResponse/SC_GATEWAY_TIMEOUT})))
           (.complete continuation)
           ;; go blocks must return non-nil
           true)))

           (javax.servlet.http HttpServletRequest HttpServletResponse)
           (org.eclipse.jetty.continuation ContinuationSupport Continuation))
  (:require
    [clojure.core.async :refer [go <!]]
    [ring.util.servlet :as servlet]
    [ring.adapter.jetty :as jetty]))



  The asychronous handler is wrapped in some Jetty-specific continuation logic
  and passed to the standard run-jetty."
  [handler {timeout-ms :async-timeout :or {timeout-ms 10000} :as options}]
  (jetty/run-jetty (wrap-with-continuation handler timeout-ms) options))