如何在 clojure/ring 中进行 http 调用?
How can I make an http call in clojure/ring?
我的 Web 客户端(用 cljs
编写)连接到后端(用 clj
编写)需要进行一些第三方 API 调用。它必须在服务器上完成,然后将结果以特定方式转换并发送回客户端。
这是我对其中一个网址的处理程序
(defn get-orders [req]
(let [{:keys [sig uri]} (api-signature :get-orders)]
(client/get uri
{:async? true}
(fn [response] {:body "something"})
(fn [exception] {:body "error"}))))
它没有返回 {:body "something"}
,而是返回以下错误:
No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: org.apache.http.impl.nio.client.FutureWrapper
我做错了什么?
当您指定 {:async? true}
时,clj-http.client/get
将 return a future,这是您收到的错误消息中的 FutureWrapper
。
所以如果你不需要异步,就不要使用它。这是调用第三方 url 和 return 返回的响应的同步环处理程序的示例。
(defn handler [request]
(response {:result (client/get "http://example.com")}))
如果您确实需要异步,请使用环处理程序的异步版本。
(defn handler [request respond raise]
(client/get "http://example.com"
{:async? true}
(fn [response] (respond {:body "something"}))
(fn [exception] (raise {:body "error"}))))
不要忘记配置网络服务器适配器以使用异步处理程序。例如,对于 Jetty,将 :async?
标志设置为 true
,就像这样
(jetty/run-jetty app {:port 4000 :async? true :join? false})
如果要同时调用多个第三方url和return一次调用web客户端,使用promise来帮助
(defn handler [request]
(let [result1 (promise)
result2 (promise)]
(client/get "http://example.com/"
{:async? true}
(fn [response] (deliver result1 {:success true :body "something"}))
(fn [exception] (deliver result1 {:success false :body "error"})))
(client/get "http://example.com/"
{:async? true}
(fn [response] (deliver result2 {:success true :body "something"}))
(fn [exception] (deliver result2 {:success false :body "error"})))
(cond
(and (:success @result1)
(:success @result2))
(response {:result1 (:body @result1)
:result2 (:body @result2)})
(not (:success @result1))
(throw (ex-info "fail1" (:body @result1)))
(not (:success @result2))
(throw (ex-info "fail2" (:body @result2))))))
我的 Web 客户端(用 cljs
编写)连接到后端(用 clj
编写)需要进行一些第三方 API 调用。它必须在服务器上完成,然后将结果以特定方式转换并发送回客户端。
这是我对其中一个网址的处理程序
(defn get-orders [req]
(let [{:keys [sig uri]} (api-signature :get-orders)]
(client/get uri
{:async? true}
(fn [response] {:body "something"})
(fn [exception] {:body "error"}))))
它没有返回 {:body "something"}
,而是返回以下错误:
No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: org.apache.http.impl.nio.client.FutureWrapper
我做错了什么?
当您指定 {:async? true}
时,clj-http.client/get
将 return a future,这是您收到的错误消息中的 FutureWrapper
。
所以如果你不需要异步,就不要使用它。这是调用第三方 url 和 return 返回的响应的同步环处理程序的示例。
(defn handler [request]
(response {:result (client/get "http://example.com")}))
如果您确实需要异步,请使用环处理程序的异步版本。
(defn handler [request respond raise]
(client/get "http://example.com"
{:async? true}
(fn [response] (respond {:body "something"}))
(fn [exception] (raise {:body "error"}))))
不要忘记配置网络服务器适配器以使用异步处理程序。例如,对于 Jetty,将 :async?
标志设置为 true
,就像这样
(jetty/run-jetty app {:port 4000 :async? true :join? false})
如果要同时调用多个第三方url和return一次调用web客户端,使用promise来帮助
(defn handler [request]
(let [result1 (promise)
result2 (promise)]
(client/get "http://example.com/"
{:async? true}
(fn [response] (deliver result1 {:success true :body "something"}))
(fn [exception] (deliver result1 {:success false :body "error"})))
(client/get "http://example.com/"
{:async? true}
(fn [response] (deliver result2 {:success true :body "something"}))
(fn [exception] (deliver result2 {:success false :body "error"})))
(cond
(and (:success @result1)
(:success @result2))
(response {:result1 (:body @result1)
:result2 (:body @result2)})
(not (:success @result1))
(throw (ex-info "fail1" (:body @result1)))
(not (:success @result2))
(throw (ex-info "fail2" (:body @result2))))))