Clojure building of URL from constituent parts

后端 未结 5 1204
余生分开走
余生分开走 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:20

    Here's one way:

    user=> (import [java.net URLEncoder])                                                      
    java.net.URLEncoder
    user=> (str "http://stackoverflow.com/search?q=" (URLEncoder/encode "clojure url" "UTF-8"))
    "http://stackoverflow.com/search?q=clojure+url"
    

    I know this is not exactly the same as your Python snippet though. Please see the following post from the Clojure mailing list for a more complete answer:

    http://www.mail-archive.com/clojure@googlegroups.com/msg29338.html

    The code from there will allow you to do this:

    user=> (encode-params {"q" "clojure url"})
    "q=clojure+url"
    
    0 讨论(0)
  • 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"
    
    0 讨论(0)
  • 2021-02-07 18:31

    A simple solution using str(ings):

    (def q (str "clojure+url"))
    (def url (str "http://stackoverflow.com/search?" q))
    
    0 讨论(0)
  • 2021-02-07 18:43

    This is the exact REPL equivalent of your python session, using clj-http.

    user=> (require ['clj-http.client :as 'client])
    nil
    user=> (str "http://stackoverflow.com/search?"
    user=*      (client/generate-query-string {"q" "clojure url"}))
    "http://stackoverflow.com/search?q=clojure+url"
    

    but clj-http makes it even easier:

    user=> (client/get "http://stackoverflow.com/search?"
    user=*             {:query-params {"q" "clojure url"}})
    ... <a lot of output, omitted to protect the innocent>...
    

    assuming that you want to perform a GET request, that is.

    0 讨论(0)
  • 2021-02-07 18:43

    clj-apache-http is pretty useful. With it you can do the following:

    user=> (require ['com.twinql.clojure.http :as 'http])
    nil
    user=> (def q (http/encode-query {"q" "clojure url"}))
    #'user/q
    user=> (def url (str "http://stackoverflow.com/search?" q))
    #'user/url
    user=> url
    "http://stackoverflow.com/search?q=clojure+url"
    
    0 讨论(0)
提交回复
热议问题