我正在使用 Sente 库通过 websockets 进行通信。通信已经开始,但会话似乎丢失了。我正在像这样设置 Sente:
;; According to https://github.com/ptaoussanis/sente
(let [{:keys [ch-recv send-fn connected-uids
ajax-post-fn ajax-get-or-ws-handshake-fn]}
(sente/make-channel-socket! (get-sch-adapter) {})]
(def ring-ajax-post ajax-post-fn)
(def ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn)
(def ch-chsk ch-recv) ; ChannelSocket's receive channel
(def chsk-send! send-fn) ; ChannelSocket's send API fn
(def connected-uids connected-uids)) ; Watchable, read-only atom
(defmulti handle-message
"Multimethod to handle messages coming from the clients"
:id)
(defmethod handle-message
:default
[{:as ev-msg :keys [event id ?data ring-req ?reply-fn send-fn]}]
(let [session (:session ring-req)
uid (:uid session)]
(printf "Ring request: %s\n" ring-req)
(printf "Session: %s\n" session)
(printf "UID: %s\n" uid)
(printf "Unhandled event: %s\n" event)
(printf "Thread id: %s\n" (.getId (Thread/currentThread)))
(flush)
(when ?reply-fn
(?reply-fn {:umatched-event-as-echoed-from-from-server event}))))
(defmethod handle-message :chsk/ws-ping [arg]
(println "ping")) ; Ignore pings
(mount/defstate ^{:on-reload :noop}
socket-server
:start (sente/start-server-chsk-router!
ch-chsk
(fn [arg]
(handle-message arg)
(println "\n"))
#_{:simple-auto-threading? true})
:stop (socket-server))
当我从经过身份验证的客户端发送消息时,我得到以下输出:
Ring request: {:identity nil, :cookies {"ring-session" {:value "8df3a322-313a-4f16-873c-9ea7275af723"}}, :remote-addr "0:0:0:0:0:0:0:1", :params {:client-id "7a2d8913-ad69-4c82-83ed-30ffb1e3c50a"}, :flash nil, :route-params {}, :headers {"origin" "file://", "host" "localhost:3000", "upgrade" "websocket", "user-agent" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) projectx/0.1.0 Chrome/52.0.2743.82 Electron/1.3.3 Safari/537.36", "cookie" "ring-session=8df3a322-313a-4f16-873c-9ea7275af723", "connection" "Upgrade", "pragma" "no-cache", "sec-websocket-key" "g9lEvc59vyaE6RLbM36iyQ==", "accept-language" "en-US", "sec-websocket-version" "13", "accept-encoding" "gzip, deflate", "sec-websocket-extensions" "permessage-deflate; client_max_window_bits", "cache-control" "no-cache"}, :async-channel #object[org.httpkit.server.AsyncChannel 0x8958245 "/0:0:0:0:0:0:0:1:3000<->/0:0:0:0:0:0:0:1:64374"], :server-port 3000, :content-length 0, :form-params {}, :compojure/route [:get "/web-socket"], :websocket? true, :session/key nil, :query-params {"client-id" "7a2d8913-ad69-4c82-83ed-30ffb1e3c50a"}, :content-type nil, :character-encoding "utf8", :uri "/web-socket", :server-name "localhost", :query-string "client-id=7a2d8913-ad69-4c82-83ed-30ffb1e3c50a", :body nil, :multipart-params {}, :scheme :http, :request-method :get, :session {}}
Session: {}
UID: null
Unhandled event: [:projectx.core/boo "boo!"]
Thread id: 38
处理程序非常简单,设置如下:
(def app-routes
(routes
(GET "/web-socket" req (socket/ring-ajax-get-or-ws-handshake req))
(POST "/web-socket" req (socket/ring-ajax-post req))
#'service-routes
(route/not-found
"page not found")))
(defn app [] (middleware/wrap-base #'app-routes))
middleware/wrap-base 包含会话处理,它看起来像这样:
(defn wrap-identity [handler]
(fn [request]
(println (:cookies request))
(if-let [current-user-id (get-in request [:session :identity])]
(if-let [current-user (when current-user-id (db/get-user-by-id {:id current-user-id}))]
(handler (assoc request :current-user current-user))
(handler (-> request
(dissoc :identity)
(dissoc-in [:session :identity])))))
(handler request))))
(defn wrap-auth [handler]
(let [backend (session-backend)]
(-> handler
wrap-identity
(wrap-authentication backend)
(wrap-authorization backend))))
(defn wrap-base [handler]
(-> ((:middleware defaults) handler)
wrap-auth
(wrap-defaults
(-> site-defaults
(assoc-in [:params :keywordize] true) ; Needed by Sente: https://github.com/ptaoussanis/sente#on-the-server-clojure-side
(assoc-in [:params :urlencoded] true) ; Needed by Sente: https://github.com/ptaoussanis/sente#on-the-server-clojure-side
(assoc-in [:security :anti-forgery] false)
(assoc-in [:session :store] (ttl-memory-store (* 60 30)))))))
这适用于 AJAX 请求。我什至尝试在会话中设置 :uid 以及在用户登录后在客户端中启动通道,但没有改变会话保持为空的事实。