Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

option to pre-process :query-params #642

Open
raymcdermott opened this issue Feb 13, 2024 · 2 comments
Open

option to pre-process :query-params #642

raymcdermott opened this issue Feb 13, 2024 · 2 comments

Comments

@raymcdermott
Copy link

When making API calls to an external provider, we need to have the query parameters in camelCase rather than our beloved kebab-case 😢

To achieve this we have a small function which, as you can imagine, works fine.

(def kebab->camel (partial cske/transform-keys csk/->camelCaseString))

(let [api-query-params (kebab->camel query-params)
       request-opts (assoc arguments :query-params api-query-params)
       results (client request-opts)]
...

It would be nice if there was an option to automate this on the client since I imagine that this is a fairly common requirement.

Would you accept a PR?
Must the PR avoid the extra dependency on camel-snake-kebab?

@kpassapk
Copy link

Maybe this could be done through middleware? And added to the list of contributed middleware in this repo.

@fr33m0nk
Copy link

fr33m0nk commented Jul 24, 2024

I had a similar need but for :body.
query-string mw definitely is a bit mouthful as :query-string field contains value as string e.g. if {:query-params {:user-id 1 :teaId 2}} then :query-string is "user-id=1&teaId=2".

(require '[clj-http.client :as clj-http] '[camel-snake-kebab.core :as csk] '[camel-snake-kebab.extras :as cske])

;; a lengthy yet trivial middleware
(defn- encode-qs-mw
  "a Middleware for encoding query params."
  [client]
  (let [qs-kebab->camel
        (fn [req]
          (if-let [qs (:query-string req)]
            (assoc req :query-string (->> (str/split qs #"&")
                                          (map (comp
                                                 (partial str/join "=")
                                                 (juxt (comp csk/->camelCaseString first) second)
                                                 #(str/split % #"=")))
                                          (str/join "&")))
            req))]
    (fn
      ([req]
       (client (qs-kebab->camel req)))
      ([req respond raise]
       (client (qs-kebab->camel req)
               respond
               raise)))))

In action:

(clj-http/with-additional-middleware
  [encode-qs-mw]
  (clj-http/get "https://jsonplaceholder.typicode.com/posts" 
                {:debug true
                 :query-params {:user-id 1 :teaId 2}}))

;;=> 
;; Request logs

;; Request: nil
;;{:user-info nil,
;; :use-header-maps-in-response? true,
;; :body-type nil,
;; :debug true,
;; :headers {"accept-encoding" "gzip, deflate"},
;; :server-port nil,
;; :url "https://jsonplaceholder.typicode.com/posts",
;; :flatten-nested-keys (:query-params),
;; :uri "/posts",
;; :server-name "jsonplaceholder.typicode.com",
;; :query-string "userId=1&teaId=2",   ;; <<-- what was intended
;; :body nil,
;; :scheme :https,
;; :request-method :get}
;;HttpRequest:
;;{:config nil,
;; :method "GET",
;; :requestLine
;; #object[org.apache.http.message.BasicRequestLine 0x6a9ff8e9 "GET https://jsonplaceholder.typicode.com/posts?userId=1&teaId=2 HTTP/1.1"],
;; :aborted false,
;; :params
;; #object[org.apache.http.params.BasicHttpParams 0x74f2986c "[parameters={}]"],
;; :protocolVersion
;; #object[org.apache.http.HttpVersion 0x7aa51a2a "HTTP/1.1"],
;; :URI
;; #object[java.net.URI 0x6d630e1f "https://jsonplaceholder.typicode.com/posts?userId=1&teaId=2"],
;; :class org.apache.http.client.methods.HttpGet,
;; :allHeaders
;; [#object[org.apache.http.message.BasicHeader 0x1b574644 "Connection: close"],
;;  #object[org.apache.http.message.BasicHeader 0x29c2be0d "accept-encoding: gzip, deflate"]]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants