Closed ptaoussanis closed 1 year ago
hi @ptaoussanis sorry for late response being pretty busy during weekdays. I will experiment the upgrade by myself and come back to you if there is any updates/questions.
No problem at all @sunng87, and thank you so much 🙏 Please take the time you need.
I had a quick look into original jetty adapter, we will need to change ring-req->server-ch-resp
to:
(deftype JettyServerChanAdapter []
i/IServerChanAdapter
(ring-req->server-ch-resp [_ req callbacks-map]
(jetty/ws-upgrade-response
(server-ch-resp (jetty/ws-upgrade-request? req) callbacks-map))))
Just wrap the callbacks with jetty/ws-upgrade-response
and it will take care of the upgrade handshake.
And for sch-send!
implementation, I'm afraid we cannot use (ajax-cbs sch)
here. The callback is Jetty's websocket write callback and it has nothing to do with our ajax implementation. We can get the result of write, our return value for sch-send!
via this callback. However it's an async approach that may not fit into our current api.
I haven't been able to figure out how we can fallback to ajax when the request is not a websocket. We should be able to use the else branch of (jetty/ws-upgrade-request? req)
. But since the ajax fallback is not websocket I'm not sure if we can get a valid sch
for ajax.
Hi @sunng87, thanks a lot for taking a look at this!
However it's an async approach that may not fit into our current api. [...] I haven't been able to figure out how we can fallback to ajax when the request is not a websocket.
Can ring-jetty9-adapter
handle a normal (non-WebSocket) HTTP request so that the application can use a callback or some other way to asynchronously reply to the request when ready?
For example with http-kit:
(defn handle-ring-req [ring-req]
(let [channel (org.httpkit.server/as-channel ring-req {})]
(future
;; Later, when application is ready ...
(Thread/sleep 2000)
(org.httpkit.server/send! channel
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Reply"}))
channel))
I think Immutant and Undertow also work like this.
Can ring-jetty9-adapter
also do something like this?
It would be okay if the way to do it (API) looked different, I'd just need to see an example.
Or is this kind of async approach just fundamentally not currently possible?
Thank you!
it seems possible with ring's async api, check the async example in https://github.com/sunng87/ring-jetty9-adapter/blob/master/examples/rj9a/async.clj
for websocket, it's like:
(defn async-handler [request send-response _]
(send-response
(if (jetty/ws-upgrade-request? request)
;; if the request is a websocket upgrade, finish handshake
(jetty/ws-upgrade-response my-websocket-handler)
;; otherwise, use send-response with a ring response map
{:status 200 :body "hello"})))
We can create a channel implementation based on send-response
.
By the way, if you are using async handler, add option :async? true
when run-jetty
I see, thank you!
So if I understand correctly, it seems the only way to currently provide an async HTTP response via ring-jetty9-adapter
would be through Ring's 3-arity async handler API?
I'll experiment with adding support for Ring's 3-arity async handlers to the next version of Sente 👍
This issue can be closed from my side, thanks again!
Thank you @ptaoussanis ! Let me know if you have any further questions!
Hi Ning, thanks a lot for all your work on ring-jetty9-adapter!
Context
I maintain a Clojure/Script library called Sente. It provides an API to help make it easier for web apps to use WebSockets for client<->server communication.
Sente currently supports a number of Clojure web servers, incl. http-kit and ring-undertow-adapter.
Sente also previously supported ring-jetty9-adapter, but support seems to have been broken sometime around https://github.com/sunng87/ring-jetty9-adapter/pull/59.
I'm currently working on a major upcoming update to Sente (v1.18), and it'd be great to get ring-jetty9-adapter support working again.
The trouble is that I've not yet had the opportunity to use ring-jetty9-adapter myself - and I haven't been able to find the info I need about the API online.
Would you maybe be available to assist with this?
Details of what's needed
To support a web-server like ring-jetty9-adapter, Sente needs an "adapter" that implements these 2 protocols.
Example implementations:
This is currently what I have:
Any assistance/advice would be very much appreciated, thanks!
Cheers :-)