从组成部分构建URL的clojure

qre*_*est 13 url clojure

在Python中我会做以下事情:

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

>>> url = "http://stackoverflow.com/search?" + q
>>> url
'http://stackoverflow.com/search?q=clojure+url'
Run Code Online (Sandbox Code Playgroud)

如何在Clojure中完成上面为我完成的所有编码?换句话说,我该怎么做类似以下的事情:

=> (build-url "http://stackoverflow.com/search" {"q" "clojure url"})
"http://stackoverflow.com/search?q=clojure+url"
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyk 19

url-encodeRing的ring.util.codec命名空间中有一个函数:

(ring.util.codec/url-encode "clojure url")
; => "clojure+url"
Run Code Online (Sandbox Code Playgroud)

我不确定是否有预先打包的功能将地图转换为查询字符串,但也许这可以完成这项工作:

(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)))
Run Code Online (Sandbox Code Playgroud)

一个例子:

user> (make-query-string {"q" "clojure url" "foo" "bar"})
"q=clojure+url&foo=bar"
Run Code Online (Sandbox Code Playgroud)

剩下的就是将结果连接到URL的末尾:

(defn build-url [url-base query-map]
  (str url-base "?" (make-query-string query-map)))
Run Code Online (Sandbox Code Playgroud)

似乎工作:

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

更新:

也许修改后的版本可能会带来更友好的Clojure体验.还通过一个Ring样式的可选参数处理编码,默认为utf-8.

(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)))
Run Code Online (Sandbox Code Playgroud)

所以现在我们可以做到

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


Mic*_*ohl 12

这是一种方式:

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"
Run Code Online (Sandbox Code Playgroud)

我知道这与你的Python片段不完全相同.请参阅Clojure邮件列表中的以下帖子以获得更完整的答案:

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

那里的代码将允许您这样做:

user=> (encode-params {"q" "clojure url"})
"q=clojure+url"
Run Code Online (Sandbox Code Playgroud)


0x8*_*x89 11

这是使用clj-http的 python会话的精确REPL等价物.

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"
Run Code Online (Sandbox Code Playgroud)

但clj-http让它更容易:

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

假设您要执行GET请求,即.