2010-09-04 5 views
12

En Python je faire ce qui suit:bâtiment Clojure des URL de parties constitutives

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

>>> url = "http://stackoverflow.com/search?" + q 
>>> url 
'http://stackoverflow.com/search?q=clojure+url' 

Comment puis-je faire tout le codage qui est fait pour moi ci-dessus dans Clojure? En d'autres termes, comment dois-je faire quelque chose de semblable à ce qui suit:

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

Répondre

12

Voici une façon:

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" 

Je sais Ce n'est pas exactement la même chose que votre extrait Python. S'il vous plaît voir le message suivant de la liste de diffusion Clojure pour une réponse plus complète:

http://www.mail-archive.com/[email protected]/msg29338.html

Le code à partir de là vous permettra de le faire:

user=> (encode-params {"q" "clojure url"}) 
"q=clojure+url" 
+0

En remarquant le montage, je suppose que je n'aurais pas dû m'embêter à écrire tout ça ... Oh bien. +1 pour la première réponse complète. J'aime toujours ma version 'Named'-handling, donc je laisse ça ici. :-) –

0

Une solution simple en utilisant str (Ings):

(def q (str "clojure+url")) 
(def url (str "http://stackoverflow.com/search?" q)) 
+0

Eh bien, vous donnez «+» comme entrée, donc vous ne laissez pas Clojure encoder la chaîne pour vous. –

18

Il y a une fonction url-encode dans Anneau ring.util.codec espace de noms:

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

Je ne sais pas s'il y a une fonction préemballée de transformer une carte en Quer chaîne y, mais peut-être cela pourrait faire le travail:

(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))) 

Un exemple:

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

Tout ce qui reste est concaténer le résultat sur la fin d'une URL:

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

Semble pour travailler:

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

Mise à jour:

Peut-être une version modifiée pourrait faire pour une plus grande expérience Clojure conviviale. Gère également l'encodage via un argument optionnel Ring-style avec utf-8 par défaut.

(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))) 

Alors maintenant, nous pouvons faire

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

Ah, presque oublié: 'ring.util.codec' prend également un argument de codage optionnel, par défaut' UTF-8'. –

2

clj-apache-http est très utile. Avec elle, vous pouvez effectuer les opérations suivantes:

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" 
11

Ceci est l'équivalent exact REPL de votre session python, en utilisant 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" 

mais CLJ-http rend encore plus facile:

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

en supposant que vous souhaitez effectuer une requête GET, ce qui est.