Skip to content

Instantly share code, notes, and snippets.

@currentoor
Last active December 6, 2018 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save currentoor/dd03ff63d7b44711484309a06953b209 to your computer and use it in GitHub Desktop.
Save currentoor/dd03ff63d7b44711484309a06953b209 to your computer and use it in GitHub Desktop.
(ns ucv.server.websocket-channel-listener
(:require
[fulcro.websockets.protocols :refer [WSListener add-listener remove-listener]]
[mount.core :refer [defstate args]]
[taoensso.timbre :as log]
[ucv.server.websockets :refer [websockets]]))
;;; Fulcro's component sticks the result of user-id-fn into the top level of
;;; env, for mutations to use.
(defrecord ChannelListener []
WSListener
(client-dropped [this ws-net cid]
(log/info "Client disconnected " cid))
(client-added [this ws-net cid]
(log/info "Client connected " cid)))
(defstate channel-listener
:start (let [listener (->ChannelListener)]
(add-listener websockets listener)
listener)
:stop (remove-listener websockets channel-listener))
(ns ucv.server.middleware
(:require
[mount.core :refer [defstate]]
[ring.middleware.gzip :refer [wrap-gzip]]
[ring.middleware.defaults :refer [wrap-defaults]]
[ring.util.response :as resp :refer [response file-response resource-response]]
[ring.middleware.session :refer [wrap-session]]
[taoensso.timbre :as log]
[fulcro.server :as server]
[ucv.server.websockets :as s.websockets]
[ucv.server.config :as s.config]))
(defn- is-wsrequest? [{:keys [uri]}] (= "/chsk" uri))
(defn wrap-websockets
"Add websocket middleware. This middleware does a CSRF check on the GET
(normal Ring only checks POSTS) to ensure we don't start a Sente handshake
unless the client has already proven it knows the CSRF token."
[base-request-handler]
(fn [{:keys [request-method] :as req}]
(if (is-wsrequest? req)
(let [{:keys [ring-ajax-post ring-ajax-get-or-ws-handshake]} s.websockets/websockets]
;; The enforcement is really on GET, which ring's middleware won't block,
;; but which exposes the token in the handshake
(case request-method
:get (ring-ajax-get-or-ws-handshake req)
:post (ring-ajax-post req)))
(base-request-handler req))))
(defstate middleware
:start
(let [defaults-config (:ring.middleware/defaults-config s.config/config)
legal-origins (get s.config/config :legal-origins #{"localhost"})]
(-> not-found-handler
wrap-websockets
(wrap-api "/api")
server/wrap-transit-params
server/wrap-transit-response
(wrap-html5-routes)
wrap-gzip)))
(ns ucv.server.websockets
(:require [com.stuartsierra.component :as component]
[fulcro.websockets :as fw]
[mount.core :refer [defstate]]
[taoensso.sente.server-adapters.immutant :refer [get-sch-adapter]]
[ucv.auth :as auth]
[ucv.server.parser :as s.parser]
[ucv.util :as util]))
(defn user-id-fn [{:as hand-shake-req :keys [client-id params]}]
(let [claims (auth/verify-request hand-shake-req)
authed? (::auth/valid? claims)
user-id (if authed?
(:user-id claims)
(or (:onsite-id params)
client-id))]
user-id))
(defstate websockets
:start
(let [websockets (fw/make-websockets
s.parser/parser
{:http-server-adapter (get-sch-adapter)
:sente-options {:user-id-fn user-id-fn}})]
(component/start websockets))
:stop
(component/stop websockets))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment