kit-clj / kit

Lightweight, modular framework for scalable web development in Clojure
https://kit-clj.github.io/
MIT License
475 stars 44 forks source link

Sente websocket integration / module #51

Closed markokocic closed 2 years ago

markokocic commented 2 years ago

Just came across Sente library, which allows a two-way communication between a client and a server.

I'm already considering hooking it up to the re-frame even bus, and use in an application to communicate with the server instead of using the REST API.

Before I spend more time on this topic, I'd like to know is there a good example how it could fit in kit application architecture. A module to wire the basics would be even better.

yogthos commented 2 years ago

Sente would work similarly to this Luminus example, the only thing to change would be to use an Integrant ig/init-key and ig/halt-key to create the router instead of Mount defstate.

markokocic commented 2 years ago

Thanks @yogthos .

I actually tried to convert at least a communication part of the luminus example to kit. I got to the point that I don't see any errors, socket connection seems to be established, but message-hanlder! on server is not receiving any event.

I probably missed either something obvious, or I am doing something wrong with integrant.

The server-side code is at ws.clj and system.edn

yogthos commented 2 years ago

The wiring on the server looks correct to me as well. I wonder if it might be the middleware you're adding that could be causing the problem. In particular, wrap-anti-forgery might be an issue. However, you probably don't want to wrap a separate session around ws either. I'd recommend having a single session wrapper higher up the middleware stack that will be shared by all route groups.

markokocic commented 2 years ago

Hi @yogthos, thanks for the tip. Now that I disabled wrap-anti-forgery middleware and csrf-token checking in sente, it appears to work. Complete example is now at kit-sente-playground

It uses multimethods on server to handle events, while I left the client intentionally bare (only logging response) to be free to decide whether one wants to use multimethods, re-frame event bus or something else.

Would you be interested in wrapping it up and contributing it as a kit module? If yes, do you have some suggestions how to clean it up (naming, code organization)?

Some suggestions how to add it, especially on client side. I can add ws.cljs to requires in the core.cljs, but not sure how to modify it to add buttons that invoke example events and how to add init function to be executed at startup.

markokocic commented 2 years ago

I created a pull request to add sente module, but got blocked by #53

Once that is completed, the only missing/manual part would be updating core.cljs to initialise ws and add handler function.

markokocic commented 2 years ago

Anothre issue is that in html I am not able to specify the location where to inject a javascript snippet.

I have the following injection defined.

                {:type   :html
                 :path   "resources/html/home.html"
                 :action :append
                 :target [:body]
                 :value  [:script {:type "text/javascript"} "var csrfToken = '{{csrf-token}}';"]}

Obviously, this will create a javascript snippet at the end of the html body section, after the section that includes app.js. Javascript loading would then fail, since csrfToken is not defined before it's used (in ws.cljs).

As a workaround I put the script tag in html head, but it may make sense to extend the injection framework to specify the exact location (:before, :after, ...)

yogthos commented 2 years ago

Hi, adding a module is a good plan. What you could do is add a dependency on the existing cljs module that does the wiring for the front end. Then the ws module only needs to add ws specific templates.

yogthos commented 2 years ago

Ah, I see the module's already piggybacking on cljs. :) And agree with the idea of adding :before and :after hints for injections. Might be worth adding an issue for doing that.

markokocic commented 2 years ago

What would also be missing is the ability to create a new function or update existing in an clj file. Then no manual steps would be required after installing a module.

markokocic commented 2 years ago

Merged :kit/sente module and added documentation in JavaScript section.