-
Notifications
You must be signed in to change notification settings - Fork 3
/
core.clj
87 lines (77 loc) · 2.4 KB
/
core.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
84
85
86
87
(ns json-rpc.core
(:refer-clojure :exclude [send])
(:require
[clojure.tools.logging :as log]
[json-rpc.client :as client]
[json-rpc.http :as http]
[json-rpc.json :as json]
[json-rpc.unix :as unix]
[json-rpc.url :as url]
[json-rpc.ws :as ws]))
(def ^:const version
"JSON-RPC protocol version."
"2.0")
(defn uuid
[]
(.toString (java.util.UUID/randomUUID)))
(defn encode
"Encodes JSON-RPC method and params as a valid JSON-RPC request."
([method params id]
(let [request {:jsonrpc version
:method method
:params params
:id id}
encoded (json/write-str json/data-json request)]
(log/debugf "map => %s, json => %s" request encoded)
encoded))
([method params]
(encode method params (uuid))))
(defn decode
"Decodes result or error from JSON-RPC response"
[json]
(let [body (json/read-str json/data-json json)]
(log/debugf "json => %s, map => %s" json body)
(select-keys body [:result :error :id])))
(def ^:private ^:const routes
{:http http/clj-http
:https http/clj-http
:ws ws/gniazdo
:wss ws/gniazdo
:unix unix/unix-socket})
(defn route
[url]
(let [scheme (url/scheme url)]
(if-let [client (routes scheme)]
client
(throw (ex-info (format "Unsupported scheme: %s. Supported schemes are: %s."
(url/scheme url)
(keys routes))
{:url url})))))
(defrecord Channel [send-fn close-fn]
java.io.Closeable
(close [this]
(close-fn)))
(defn open
[url & {route-fn :route-fn}]
(let [route-fn (or route-fn route)
client (route-fn url)
channel (client/open client url)]
(log/debugf "url => %s" url)
(map->Channel {:send-fn (partial client/send client channel)
:close-fn #(client/close client channel)})))
(defn send
[{send-fn :send-fn} method params & {id :id}]
(let [id (or id (uuid))
request (encode method params id)
response (-> request
(send-fn))
decoded (decode response)]
(log/debugf "request => %s, response => %s" request response)
(if (= id (:id decoded))
decoded
(throw (ex-info "Response ID is different from request ID!"
{:request request
:response response})))))
(defn close
[{close-fn :close-fn}]
(close-fn))