-
Notifications
You must be signed in to change notification settings - Fork 517
/
websocket.clj
83 lines (74 loc) · 2.71 KB
/
websocket.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
(ns ring.websocket
"Protocols and utility functions for websocket support."
(:refer-clojure :exclude [send])
(:require [clojure.string :as str]
[ring.websocket.protocols :as p])
(:import [java.nio ByteBuffer]))
(extend-type clojure.lang.IPersistentMap
p/Listener
(on-open [m socket]
(when-let [kv (find m :on-open)] ((val kv) socket)))
(on-message [m socket message]
(when-let [kv (find m :on-message)] ((val kv) socket message)))
(on-pong [m socket data]
(when-let [kv (find m :on-pong)] ((val kv) socket data)))
(on-error [m socket throwable]
(when-let [kv (find m :on-error)] ((val kv) socket throwable)))
(on-close [m socket code reason]
(when-let [kv (find m :on-close)] ((val kv) socket code reason)))
p/PingListener
(on-ping [m socket data]
(if-let [kv (find m :on-ping)]
((val kv) socket data)
(p/-pong socket data))))
(defn open?
"Returns true if the Socket is open, false otherwise."
[socket]
(boolean (p/-open? socket)))
(defn send
"Sends text or binary data via a websocket, either synchronously or
asynchronously with callback functions. A convenient wrapper for the -send and
-send-async protocol methods."
([socket message]
(p/-send socket message))
([socket message succeed fail]
(p/-send-async socket message succeed fail)))
(defn ping
"Sends a ping message via a websocket, with an optional byte array or
ByteBuffer that may contain custom session data. A convenient wrapper for the
-ping protocol method."
([socket]
(p/-ping socket (ByteBuffer/allocate 0)))
([socket data]
(p/-ping socket data)))
(defn pong
"Sends an unsolicited pong message via a websocket, with an optional byte
array or ByteBuffer that may contain custom session data. A convenient wrapper
for the -pong protocol method."
([socket]
(p/-pong socket (ByteBuffer/allocate 0)))
([socket data]
(p/-pong socket data)))
(defn close
"Closes the websocket, with an optional custom integer status code and reason
string."
([socket]
(p/-close socket 1000 "Normal Closure"))
([socket code reason]
(p/-close socket code reason)))
(defn upgrade-request?
"Returns true if the request map is a websocket upgrade request."
[request]
(let [headers (:headers request)]
(and (.equalsIgnoreCase "upgrade" (get headers "connection"))
(.equalsIgnoreCase "websocket" (get headers "upgrade")))))
(defn websocket-response?
"Returns true if the response contains a websocket listener."
[response]
(contains? response ::listener))
(defn request-protocols
"Returns a collection of websocket subprotocols from a request map."
[request]
(some-> (:headers request)
(get "sec-websocket-protocol")
(str/split #"\s*,\s*")))