Liking cljdoc? Tell your friends :D

logo

fulcro websockets

A websocket remote for use with Fulcro 3.0.0-beta-1+ applications.

1. Usage

Add the proper dependencies to your project. You’ll need sente, some Ring bits, and of course Fulcro 3.

1.1. Server

The server setup is mostly just standard Ring fare.

(ns my-app.websocket-server
  (:require
    [com.fulcrologic.fulcro.server.api-middleware :refer [not-found-handler]]
    [com.fulcrologic.fulcro.networking.websockets :as fws]
    [immutant.web :as web]
    [ring.middleware.content-type :refer [wrap-content-type]]
    [ring.middleware.not-modified :refer [wrap-not-modified]]
    [ring.middleware.resource :refer [wrap-resource]]
    [ring.middleware.params :refer [wrap-params]]
    [ring.middleware.keyword-params :refer [wrap-keyword-params]]
    [ring.util.response :refer [response file-response resource-response]]
    [taoensso.sente.server-adapters.immutant :refer [get-sch-adapter]]))

(def server (atom nil))

(defn query-parser
  ""
  [env query]
  ;; call out to something like a pathom parser. See Fulcro Developers Guide
  )

(defn http-server []
  (let [websockets (fws/start! (fws/make-websockets
                                 query-parser
                                 {:http-server-adapter (get-sch-adapter)
                                  :parser-accepts-env? true
                                  ;; See Sente for CSRF instructions
                                  :sente-options       {:csrf-token-fn nil}}))
        middleware (-> not-found-handler
                     (fws/wrap-api websockets)
                     wrap-keyword-params
                     wrap-params
                     (wrap-resource "public")
                     wrap-content-type
                     wrap-not-modified)
        result     (web/run middleware {:host "0.0.0.0"
                                        :port 3000})]
    (reset! server
      (fn []
        (fws/stop! websockets)
        (web/stop result)))))

(comment

  ;; start the server
  (http-server)

  ;; stop the server
  (@server))

1.2. Client

The client setup is even simpler. Just add the websocket remote as one of your remotes:

(ns my-app.client-main
  (:require
    [com.fulcrologic.fulcro.networking.websockets :as fws]
    [com.fulcrologic.fulcro.application :as app]))

(defonce app (app/fulcro-app {:remotes {:remote (fws/fulcro-websocket-remote {})}}))

1.3. Connected Clients and Server Push

The client ID management is done by Sente. The websockets component you started above has a few conveniences for you to make monitoring client connections and doing sever pushes a little easier.

To use server push you need to store your started websockets component in an atom or some other globally accessible storage (e.g. mount’s defstate). The websocket component implements a protocol that allows you to listen to client connections, and also to send push messages:

(defprotocol WSListener
  (client-added [this ws-net cid]
    "Listener for dealing with client added events.")
  (client-dropped [this ws-net cid]
    "listener for dealing with client dropped events."))

(defprotocol WSNet
  (add-listener [this ^WSListener listener]
    "Add a `WSListener` listener")
  (remove-listener [this ^WSListener listener]
    "Remove a `WSListener` listener")
  (push [this cid verb edn] "Push from server"))

So, (add-listener websockets my-listener) will add a component that you’ve written that satisfies the WSListener protocol to receive notifications when clients connect/disconnect.

The (push websockets cid :x {:value 1}) call will look up the websocket associated with the client that has cid and send the given top/value message to it. Then env of mutations and resolver (if you enable :parser-accepts-env?) will include a :cid key, so you can find out who is talking to you through normal API interactions.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close