#!/bin/sh

#_(
   true; exec clj -J--enable-preview -J-XX:-OmitStackTraceInFastThrow -Sdeps "`sed -n -e '/;;(DEPS$/,/;;DEPS)$/p' $0`" -M -i $0 -e '(user/main)'
   )

(ns user
  (:require [ring.adapter.jetty :refer [run-jetty]]
            [ring.core.protocols :as p]
            [ring.websocket :as ws]
            [ring.websocket.protocols :as wsp]))


;; run like sh ring-jetty.clj

(comment
  ;;(DEPS
  {:deps {ring/ring-core {:mvn/version "1.12.0"}
          ring/ring-jetty-adapter {:mvn/version "1.12.0"}
          }}
  ;;DEPS)
  )


(defn log [& args]
  (printf "%s %s\n" (str (java.time.Instant/now)) (apply pr-str args))
  (flush))

(in-ns 'ring.adapter.jetty)
;; monkey patch ring to add passing the async context so it can be completed

(defn- upgrade-to-websocket [ac ^HttpServletRequest request response response-map]
  (let [context   (.getServletContext request)
        container (JettyWebSocketServerContainer/getContainer context)
        creator   (websocket-creator response-map)]
    (.upgrade container creator request response)
    (.complete ac)))

(defn- async-jetty-respond [context request response]
  (fn [response-map]
    (if (ws/websocket-response? response-map)
      (upgrade-to-websocket context request response response-map)
      (servlet/update-servlet-response response context response-map))))

(in-ns 'user)


(def server (run-jetty
             (fn [req respond raise]
               (log "handler")
               (respond
                {::ws/listener
                 (reify wsp/Listener
                   (on-open [_ sock]
                     (log "sending")
                     (ws/send sock "Hello"
                              (fn []
                                (log "sent hello")
                                (ws/send sock "World"
                                         (fn []
                                           (log "sent world"))
                                         log))
                              log))
                   (on-message [_ _ _])
                   (on-pong [_ _ _])
                   (on-error [_ _ _])
                   (on-close [_ _ _ _]))}))
             {:port 3467
              :join? false
              :async? true
              :thread-idle-timeout 1
              :max-idle-time    1
              }))


(log "server started")


(.handleAsync
 (.buildAsync
  (.newWebSocketBuilder
   (java.net.http.HttpClient/newHttpClient))
  (java.net.URI. "ws://localhost:3467")
  (reify
    java.net.http.WebSocket$Listener
    (onBinary [_ _ _ _]
      (log :on-binary))
    (onClose [_ _ _ _]
      (log :on-close))
    (onOpen [_ _]
      (log :on-open))
    (onPing [_ _ _]
      (log :on-ping))
    (onPong [_ _ _]
      (log :on-pong))
    (onText [_ _ _ _]
      (log :on-text)
      (System/exit 0))
    (onError [_ _ _]
      (log :on-error))))
 (reify
   java.util.function.BiFunction
   (apply [_ a b]
     (when a
       (.request a Long/MAX_VALUE))
     (log a)
     (log b))))

(defn main []
  (.join server))

Generated At 2024-03-22T10:59:55-0700 original