Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
337 views
in Technique[技术] by (71.8m points)

Clojure ring-cors/wrap-cors setup

I'm using ring-cors and trying to pass a cors-policy for the (wrap-cors) function. This is what my code looks like:

(def cors-policy
  {:access-control-allow-origin [#"http://localhost:8080"]
   :access-control-allow-methods [:get :put :post]})

(def dev-handler (-> #'japi/routes
                     wrap-reload
                     wrap-params
                     (wrap-cors cors-policy) ;; <- Here
                     wrap-json-response
                     (wrap-defaults api-defaults)
                     push-state/handle))

This results in an error:

No value supplied for key: {:access-control-allow-origin #{"http://localhost:8080"}, :access-control-allow-methods #{:get :post :put}}

Looking at the source code for (wrap-cors) it looks like the error is coming from trying to apply (hash-map) to my cors-policy map. It seems like I cannot pass a map definition but instead I have to pass the keys/values explicitly when calling (wrap-cors). Any ideas to work around this?

I've tried (apply hash-map cors-policy) in the repl and that works fine, however when passing a dummy handler such as (wrap-cors identity cors-policy) this again results in the same error.

Edit: cfrick's answer is correct, note however that I had to remove shadow-cljs' (push-state/handle) handler at the end of my dev-handler definition for my setup to work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The wrapper uses a "pattern" that is sometimes seen and focuses on "human consumption" of the function. It takes the "rest" of the arguments and turns the pairs of it into a map. This is already "meh" for humans and is utterly bad for machines (e.g. to pass as arguments).

You have to do the call it like this:

(wrap-cors $handler :a 1 :b 2)

So the easiest way from here would be:

(def cors-policy
  [:a 1
   :b 2])

(apply wrap-cors $handler cors-policy)

Or if you want to stick with the map (IMHO a good approach), you have to flatten the map beforehand. e.g.

(apply wrap-cors $handler (into [] cat cors-policy))

But with the use of the threading macro -> this becomes harder to do now (-> is just a macro and the resulting code would be (apply $handler wrap-cors ...) which is unintended.

So at this point I'd add my own defn that just takes the handler again. E.g. something like

(defn cors-wrapper
  [handler config-map]
  (apply wrap-cors handler (into [] cat config-map)))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...