Rubyには標準でnet/httpが入っていますが、これはちょっと低レイヤ寄りで使いづらいので、使いやすくしたHTTPクライアントライブラリが多数あります。
ありすぎてどれを選んでいいか調べていたところ、HTTPClientの作者さんによる比較スライドを見つけました:
http://www.slideshare.net/HiroshiNakamura/rubyhttp-clients-comparison
まとめると
- httpartyとrest-clientが2大人気(ソースはGemのダウンロード数とgithubのスター数。faradayはラッパーなので別枠)
- この2つで出来ることはほとんど同じ
- 違いはDigest認証(httppartyは可)、multipart post(rest-clientは可)くらい
- どちらもKeep-Aliveに対応していない
- HTTPClientはDigest認証も対応しているし、Keep-Aliveも自動的に面倒見てくれるし、機能的にはフルカバーっぽい
こちらの記事でも「HTTPClientは宣伝がうまくないだけでベストなgemだ」みたいな事が書かれている。
https://bibwild.wordpress.com/2012/04/30/httpclient-is-a-nice-http-client-forin-ruby/
…しかし、もしかしたらすでにfaradayがデファクトスタンダードになりつつあるのかもしれない。
faradayの短所はドキュメントがしっかりしてないことだな。
HTTPClientの使い方
require 'httpclient'
client = HTTPClient.new
client.debug_dev = $stderr # デバッグ情報を標準エラー出力に
query = {'q' => 'google 倒産', 'hl' => 'ja'}
# get
res = client.get('https://google.co.jp', :query => query, :follow_redirect => true)
# post
#res = client.post('http://httpbin.org/post', :body => query)
puts "code=#{res.code}" # res.code : Fixnum
puts HTTP::Status.successful?(res.code)
p res.headers
puts res.body
github:https://github.com/nahi/httpclient
ドキュメント:http://www.rubydoc.info/gems/httpclient/HTTPClient
プロキシの使用
HTTPClientは(net/httpと同じく)環境変数http_proxy
を参照する。
明示的にプロキシを指定したい場合は:
proxy = 'http://**********:8080'
client = HTTPClient.new(proxy)
# さらにプロキシにBASIC認証したい場合は:
#user = 'proxy'
#password = 'proxy'
#client.set_proxy_auth(user, password)
#p client.get(url)
環境変数http_proxy
を無視してプロキシを使用しないようにするには:
client = HTTPClient.new
client.proxy = nil
リクエストヘッダの指定
res = client.get('https://google.co.jp', query: query, header: [["User-Agent", "hoge"]], follow_redirect: true)
Faradayの使い方
一番シンプルな方法
require "faraday"
res = Faraday.get "http://httpbin.org/get", {a: "hoge"}
res = Faraday.post "http://httpbin.org/post", {a: "hoge"}
p res.status # => 200
p res.success? # => true
res.headers.each do |k, v|
puts "#{k}: #{v}"
end
puts res.body
もう少し凝った方法
conn = Faraday.new(:url => 'http://sushi.com') do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
## GET ##
response = conn.get '/nigiri/sake.json' # GET http://sushi.com/nigiri/sake.json
response.body
conn.get '/nigiri', { :name => 'Maguro' } # GET http://sushi.com/nigiri?name=Maguro
conn.get do |req| # GET http://sushi.com/search?page=2&limit=100
req.url '/search', :page => 2
req.params['limit'] = 100
end
## POST ##
conn.post '/nigiri', { :name => 'Maguro' } # POST "name=maguro" to http://sushi.com/nigiri
# post payload as JSON instead of "www-form-urlencoded" encoding:
conn.post do |req|
req.url '/nigiri'
req.headers['Content-Type'] = 'application/json'
req.body = '{ "name": "Unagi" }'
end
## Per-request options ##
conn.get do |req|
req.url '/search'
req.options.timeout = 5 # open/read timeout in seconds
req.options.open_timeout = 2 # connection open timeout in seconds
end
ホスト部とパス部を分けずに書くこともできるらしい
faraday = Faraday.new
res = faraday.post "http://httpbin.org/post", {q: "hgoehoge", a: 123}
1行でJSONをPOSTする
res = Faraday.post "https://httpbin.org/post", JSON.generate({hoge: 123, moge: [1,2,3]}), content_type: "application/json"
標準出力でなく指定ファイルにログを吐く方法
require "logger"
my_logger = Logger.new("logfile.log")
my_logger.level = Logger::DEBUG
conn = Faraday.new(:url => "https://httpbin.org") do |faraday|
faraday.request :url_encoded
faraday.response :logger, my_logger # <-- sets a custom logger.
faraday.adapter Faraday.default_adapter
end
conn.get "/get", {hoge: 123}
net/httpの使い方
require "net/http"
require "uri"
シンプルなGET
url = "https://ipinfo.io"
puts Net::HTTP.get(URI.parse(url))
# => String(レスポンスボディ)
シンプルなPOST(x-www-form-urlencoded)
url = "https://httpbin.org/post"
params = {a: 123, b: "hoge"}
ret = Net::HTTP.post_form(URI.parse(url), params)
puts ret.code
puts ret.body
シンプルなPOST(JSON)
url = "https://httpbin.org/post"
payload = {
a: 123, b:"hoge"
}
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri.request_uri)
req["Content-Type"] = "application/json"
req.body = payload.to_json
res = http.request(req)
puts "code -> #{res.code}"
res.each_capitalized_name do |name|
value = res[name]
puts "#{name} = #{value}"
end
puts "body -> #{res.body}"
つぶやき
HTTPクライアントの使い方を調べるときは以下のやり方を抑えておこうと思った。
- シンプルなGET
- シンプルなPOST(x-www-form-urlencoded)
- JSONのPOST
- リクエストヘッダの指定
- リダイレクトをたどるか
- プロキシの指定
- BASIC認証
- ファイルのアップロード
- レスポンスのステータスコードはIntegerかStringか