Is there any support for RPC in ClojureScript?

1.4k Views Asked by At

I have a ClojureScript application and I want to make RPC calls to the server which would look like normal function core.async calls on the client side.

In order to do this for the moment I wrote the code below based on cljx. In the RPC definitions section I would have to add all the server-side functions which I want to expose as RPC to the client side.

Note: the send function is taken from here: https://dimagog.github.io/blog/clojure/clojurescript/2013/07/12/making-http-requests-from-clojurescript-with-core.async/

Is there a way to do this nicer without the boilerplate code?

Thinking about how to improve it the only idea that I have is to write a leiningen plugin which generates server side and client side code needed for RPC i.e. the part that I do at this moment using cljx. Is there a better way?

(ns myapp.shared.rpc
  (:require
     #+cljs [myapp.tools :refer [send log]]
     #+cljs [cljs.reader :as reader]
     #+clj  [clojure.tools.logging :as log]
     #+clj  [noir.response :refer [edn]]
     #+clj  [myapp.rpc :as rpc]
   ))

#+cljs (defn rpc-client [function params]
#+cljs   (log "RPC call: (" function params ")")
#+cljs   (send "POST" "/api"
#+cljs         (str "rpc=" (pr-str {:fun function :params params}))
#+cljs         (fn [x]
#+cljs           (log "RPC response:'" x "'")
#+cljs           (:response (reader/read-string x)))))


#+clj (defmulti rpc-impl #(:fun %))

#+clj (defn rpc-server [{rpc :rpc}]
#+clj    (log/info "RPC call received:" rpc)
#+clj    (let [response (-> rpc read-string rpc-impl)]
#+clj      (log/info "RPC response sent: '" response "'")
#+clj      (edn {:response response})))




;;;;; RPC definitions


#+cljs (defn demo [ & p]  (rpc-client :demo p))
#+clj  (defmethod rpc-impl :demo [{p :params}] (apply rpc/demo p))
2

There are 2 best solutions below

1
On BEST ANSWER

Here are three libraries I've seen that handle RPC. I don't have significant experience with any of them, so take my comments with a large grain of salt.

  • Castra. The most recently updated, and has a nice readme.
  • Fetch. Looks simple, sweet, and probably sufficient.
  • Shoreleave. I used this successfully a while back. It worked fine, but has not been updated in a few years.
0
On

Clojure has edn data exchange format, you can use CQRS as data exchange method