dakrone / clj-http

An idiomatic clojure http client wrapping the apache client. Officially supported version.
http://clojars.org/clj-http
MIT License
1.78k stars 408 forks source link

Is there an ability to add interceptor to all the outgoing calls at once? #595

Closed cksharma11 closed 3 years ago

rymndhng commented 3 years ago

clj-http does not have support for this built-in, and is unlikely to add support for this.

It's fairly straight forward to implement this with your application by defining a common set of options and re-using it across reuqests.

;; create a reusable set of options
(def clj-http-options {:response-interceptor (fn [resp ctx] ...)})

;; pass it in as re-usable options
(clj-http.client/get "your.url" clj-http-options)

;; merge it with other options
(clj-http.client/get "your.url" (merge clj-http-options {:as :json}))
cksharma11 commented 3 years ago

Hi @rymndhng

There are multiple places in the code where same change have to be done. Moreover, other devs who are not aware of it will not add it.

So, is there a way we can make the change just at one place and have all calls intercepted?

rymndhng commented 3 years ago

What your asking for can be achieved already in clj-http using custom middlewares.

As a start, familiarize with the custom middleware concept. See https://github.com/dakrone/clj-http#custom-middleware.

The approach above doesn't quite do what you want, but it's an important starting point.

To apply the custom middleware stack to all requests , use the Clojure function alter-var-root. Here's a small example of how you can modify all requests by adding a custom logging middleware:

(require '[clj-http.client :as http])

(defn my-logging-middleware [handler]
   (fn [req]
     (println "hello world!")
     (handler req)))

;; create a new middleware stack and put my-logging-middleware first
(def middlewares (concat [my-logging-middleware] http/default-middleware))

;; create a custom request method, applying all the middlewares
;; see https://github.com/dakrone/clj-http/blob/3.x/src/clj_http/client.clj#L1230-L1244
(def my-request  (reduce #(%2 %1) clj-http.core/request middlewares))

;; globally change the `http/request` function
(alter-var-root #'http/request (constantly my-request))

;; test this out, see the custom log meesage
> (def _ (http/get "https://www.google.com"))
;; hello world!

Good luck, and be careful! This is a powerful & feature of Clojure. However it can lead to unexpected side-effects and behaviors. Beware!