Clojure世界:Http Client

    xiaoxiao2024-04-05  125

    使用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只是它的一个模块罢了,这是另一个话题了。

    文章转自庄周梦蝶  ,原文发布时间2012-02-13

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)