Clojure building of URL from constituent parts

后端 未结 5 1197
余生分开走
余生分开走 2021-02-07 17:46

In Python I would do the following:

>>> q = urllib.urlencode({\"q\": \"clojure url\"})
>>> q
\'q=clojure+url\'

>>> url = \"http://sta         


        
5条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-07 18:23

    There is a url-encode function in Ring's ring.util.codec namespace:

    (ring.util.codec/url-encode "clojure url")
    ; => "clojure+url"
    

    I'm not sure if there's a prepackaged function to turn a map into a query string, but perhaps this could do the job:

    (use '[ring.util.codec :only [url-encode]])
    
    (defn make-query-string [m]
      (->> (for [[k v] m]
             (str (url-encode k) "=" (url-encode v)))
           (interpose "&")
           (apply str)))
    

    An example:

    user> (make-query-string {"q" "clojure url" "foo" "bar"})
    "q=clojure+url&foo=bar"
    

    All that remains is concatenating the result onto the end of a URL:

    (defn build-url [url-base query-map]
      (str url-base "?" (make-query-string query-map)))
    

    Seems to work:

    user> (build-url "http://stackoverflow.com/search" {"q" "clojure url"})
    "http://stackoverflow.com/search?q=clojure+url"
    

    Update:

    Perhaps a modified version might make for a more Clojure-friendly experience. Also handles encoding via a Ring-style optional argument with utf-8 as default.

    (defn make-query-string [m & [encoding]]
      (let [s #(if (instance? clojure.lang.Named %) (name %) %)
            enc (or encoding "UTF-8")]
        (->> (for [[k v] m]
               (str (url-encode (s k) enc)
                    "="
                    (url-encode (str v) enc)))
             (interpose "&")
             (apply str))))
    
    (defn build-url [url-base query-map & [encoding]]
      (str url-base "?" (make-query-string query-map encoding)))
    

    So now we can do

    user> (build-url "http://example.com/q" {:foo 1})
    "http://example.com/q?foo=1"
    

提交回复
热议问题