莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          Clojure世界:Http Client

          Posted on 2012-02-13 18:57 dennis 閱讀(6253) 評論(1)  編輯  收藏 所屬分類: Clojure

              使用http client提交表單或者下載網頁也是非常常見的任務,比如使用Java的時候可以用標準庫的HttpURLConnection,也可以選擇Apache Http Client。在clojure里也有這樣的類庫,這里我將介紹三個各有特色的http client實現。

              首先,我最先推薦使用clj-http這個類庫,它是Apache HttpClient的clojure wrapper,是一個提供同步API的簡單易用的Http Client。

          名稱: clj-http
          主頁:https://github.com/dakrone/clj-http
          依賴:
          [clj-http "0.3.1"]

          例子:
          (require '[clj-http.client :as client])
          (client/get "http://google.com")
          結果:
          => {:cookies {"NID" {:domain ".google.com.hk", :expires #<Date Tue Aug 14 18:20:38 CST 2012>, :path "/", :value "56=qn2OWtODE2D3fUKi_vbi44jZepOeLI9xC4Ta1JQLEicqUvIZAqr7TCmft_hq8i_FRwnFXdTK1jV2S5IrSZFyYhlAN2KcQEXgWX1iK36gM2iYPaKPihuUZDCqgiAamDOl", :version 0}, "PREF" {:domain ".google.com.hk", :expires #<Date Wed Feb 12 18:20:38 CST 2014>, :path "/", :value "ID=8b73a654ff0a2783:FF=0:NW=1:TM=1329128438:LM=1329128438:S=uEM4SsFuHlkqtVhp", :version 0}},
              :status 
          200
              :headers {
          "date" "Sun, 01 Aug 2010 07:03:49 GMT"
                        
          "cache-control" "private, max-age=0"
                        
          "content-type" "text/html; charset=ISO-8859-1"
                        }
              :body 
          "<!doctype html>"
              :trace
          -redirects ["http://google.com" "http://www.google.com/" "http://www.google.fr/"]}
          更多例子:
          (client/get "http://site.com/resources/3" {:accept :json})

          ;; Various options:
          (client
          /post "http://site.com/api"
            {:basic
          -auth ["user" "pass"]
             :body 
          "{\"json\": \"input\"}"
             :headers {
          "X-Api-Version" "2"}
             :content
          -type :json
             :socket
          -timeout 1000
             :conn
          -timeout 1000
             :accept :json})

          ;; Need to contact a server with an untrusted SSL cert
          ?
          (client
          /get "https://alioth.debian.org" {:insecure? true})

          ;; If you don
          't want to follow-redirects automatically:
          (client/get "http://site.come/redirects-somewhere" {:follow-redirects false})

          ;; Only follow a certain number of redirects:
          (client
          /get "http://site.come/redirects-somewhere" {:max-redirects 5})

          ;; Throw an exception 
          if redirected too many times:
          (client
          /get "http://site.come/redirects-somewhere" {:max-redirects 5 :throw-exceptions true})

          ;; Send form params as a urlencoded body
          (client
          /post "http//site.com" {:form-params {:foo "bar"}})

          ;; Multipart form uploads
          /posts
          ;; a map or vector works as the multipart object. Use a vector of
          ;; vectors 
          if you need to preserve order, a map otherwise.
          (client
          /post "http//example.org" {:multipart [["title" "My Awesome Picture"]
                                                        [
          "Content/type" "image/jpeg"]
                                                        [
          "file" (clojure.java.io/file "pic.jpg")]]})
          ;; Multipart values can be one of the following:
          ;; String, InputStream, File, or a 
          byte-array

          ;; Basic authentication
          (client
          /get "http://site.com/protected" {:basic-auth ["user" "pass"]})
          (client
          /get "http://site.com/protected" {:basic-auth "user:pass"})

          ;; Query parameters
          (client
          /get "http://site.com/search" {:query-params {"q" "foo, bar"}})

              clj-http的API相當的簡潔漂亮,使用起來非常便利,強烈推薦。題外,學習clojure的一個好方法就是為現有的java類庫實現一些方便的clojure wrapper。

              如果你需要異步的http client,我會推薦http.async.client這個類庫,它的API是異步形式的類似 Java的Future模式,對于clojure程序員來說應該更像是agent。

          名稱:http.async.client
          主頁:https://github.com/neotyk/http.async.client
          依賴:
          [http.async.client "0.4.1"]
          例子:
          (require '[http.async.client :as c])
          (with-open [client (c/create-client)]
            (let [response (c
          /GET client "http://neotyk.github.com/http.async.client/")]
              (prn (c
          /done? response))
              (c
          /await response)
              (prn (c
          /string response))
              (prn (c
          /status response))
              (prn (c
          /done? response))))

          輸出:
          false
          <!DOCTYPE html 
          {:code 
          200, :msg "OK", :protocol "HTTP/1.1", :major 1, :minor 1}
          true

          更多例子:
          (c/POST client "http://example.com" :body "hello world" :timeout 3000)
          (c
          /DELETE client "http://example.com")
          (c
          /POST client "http://example.com" :body "hello world" :auth {:type :basic :user "admin" :password "admin"})

          請注意,這些方法都是異步調用的,你需要通過await來等待調用完成,或者通過done?來判斷調用是否完成。
          http.async.client有個比較重要的特性就是對Http Chunked編碼的支持,分別通過LazySeq和callback的方式支持,首先看將Http chunked變成一個lazy seq:

          (with-open [client (client/create-client)] ; Create client
            (let [resp (client
          /stream-seq client :get url)]
              (doseq [s (s
          /string resp)]
                (println s))))

          這里非常關鍵的一點是stream-seq返回的chunk序列,每取一個就少一個(通過first函數),也就是說每次調用first取到的chunk都不一樣,是順序遞增,不可重復獲取的。

          通過callback方式處理:
          (with-open [client (client/create-client)] ; Create client
            (let [parts (ref #{})
                  resp (client
          /request-stream client :get url
                                              (fn [state body]
                                                (dosync (alter parts conj (string body)))
                                                [body :
          continue]))]
              ;; 
          do something to @parts
              ))
          自己傳入一個callback函數接收chunk,比如這里用一個ref累積。

          http.async.client的詳細文檔看這里:http://neotyk.github.com/http.async.client/docs.html

          最后,有興趣還可以看下aleph這個異步通訊的框架,它支持Http協議,也提供了http server和client的實現。不過它的API就沒有那么簡單明了,它的模型是類似go語言里利用channel做異步通訊的模型,http只是它的一個模塊罷了,這是另一個話題了。

          轉載請注明出處:http://www.aygfsteel.com/killme2008/archive/2012/02/13/369890.html

          評論

          # re: Clojure世界:Http Client  回復  更多評論   

          2012-05-19 15:49 by steven.cui
          很棒的類庫,正在嘗試用clojure,嘗試著做些wrapper,的確是快速入門的方式。
          主站蜘蛛池模板: 安图县| 新化县| 邵阳县| 方山县| 辽阳市| 余干县| 肥东县| 保山市| 锦州市| 天长市| 盐池县| 集安市| 恩施市| 桐梓县| 兴业县| 临高县| 长顺县| 合阳县| 汨罗市| 怀宁县| 龙门县| 易门县| 华容县| 太仆寺旗| 昌乐县| 杭锦后旗| 尉犁县| 全南县| 湘西| 长乐市| 岗巴县| 建昌县| 巧家县| 四平市| 浮梁县| 湘潭县| 三原县| 天气| 巢湖市| 诸暨市| 余姚市|